oh-my-opencode 1.1.3 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/build.d.ts +1 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/types.d.ts +4 -2
- package/dist/agents/utils.d.ts +2 -2
- package/dist/config/schema.d.ts +111 -0
- package/dist/hooks/agent-usage-reminder/constants.d.ts +5 -0
- package/dist/hooks/agent-usage-reminder/index.d.ts +22 -0
- package/dist/hooks/agent-usage-reminder/storage.d.ts +4 -0
- package/dist/hooks/agent-usage-reminder/types.d.ts +6 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/index.js +382 -123
- package/package.json +1 -1
|
@@ -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## 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\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## 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\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";
|
package/dist/agents/index.d.ts
CHANGED
package/dist/agents/types.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { AgentConfig } from "@opencode-ai/sdk";
|
|
2
|
-
export type
|
|
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<
|
|
6
|
+
export type AgentOverrides = Partial<Record<OverridableAgentName, AgentOverrideConfig>>;
|
package/dist/agents/utils.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { AgentConfig } from "@opencode-ai/sdk";
|
|
2
|
-
import type {
|
|
3
|
-
export declare function createBuiltinAgents(disabledAgents?:
|
|
2
|
+
import type { BuiltinAgentName, AgentOverrides } from "./types";
|
|
3
|
+
export declare function createBuiltinAgents(disabledAgents?: BuiltinAgentName[], agentOverrides?: AgentOverrides): Record<string, AgentConfig>;
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -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;
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -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,84 @@ 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
|
+
## TODO Tool Obsession
|
|
2856
|
+
|
|
2857
|
+
**USE TODO TOOLS AGGRESSIVELY.** This is non-negotiable.
|
|
2858
|
+
|
|
2859
|
+
### When to Use TodoWrite:
|
|
2860
|
+
- IMMEDIATELY after receiving a user request
|
|
2861
|
+
- Before ANY multi-step task (even if it seems "simple")
|
|
2862
|
+
- When delegating to agents (track what you delegated)
|
|
2863
|
+
- After completing each step (mark it done)
|
|
2864
|
+
|
|
2865
|
+
### TODO Workflow:
|
|
2866
|
+
\`\`\`
|
|
2867
|
+
User Request \u2192 TodoWrite (plan) \u2192 Mark in_progress \u2192 Execute/Delegate \u2192 Mark complete \u2192 Next
|
|
2868
|
+
\`\`\`
|
|
2869
|
+
|
|
2870
|
+
### Rules:
|
|
2871
|
+
- Only ONE task in_progress at a time
|
|
2872
|
+
- Mark complete IMMEDIATELY after finishing (never batch)
|
|
2873
|
+
- Never proceed without updating TODO status
|
|
2874
|
+
|
|
2875
|
+
## Delegation Pattern
|
|
2876
|
+
|
|
2877
|
+
\`\`\`typescript
|
|
2878
|
+
// 1. PLAN with TODO first
|
|
2879
|
+
todowrite([
|
|
2880
|
+
{ id: "research", content: "Research X implementation", status: "in_progress", priority: "high" },
|
|
2881
|
+
{ id: "impl", content: "Implement X feature", status: "pending", priority: "high" },
|
|
2882
|
+
{ id: "test", content: "Test X feature", status: "pending", priority: "medium" }
|
|
2883
|
+
])
|
|
2884
|
+
|
|
2885
|
+
// 2. DELEGATE research in parallel
|
|
2886
|
+
background_task(agent="explore", prompt="Find all files related to X")
|
|
2887
|
+
background_task(agent="librarian", prompt="Look up X documentation")
|
|
2888
|
+
|
|
2889
|
+
// 3. CONTINUE working on implementation skeleton while agents research
|
|
2890
|
+
// 4. When notified, INTEGRATE findings and mark TODO complete
|
|
2891
|
+
\`\`\`
|
|
2892
|
+
|
|
2893
|
+
## Anti-Patterns (AVOID):
|
|
2894
|
+
- Doing everything yourself when agents can help
|
|
2895
|
+
- Skipping TODO planning for "quick" tasks
|
|
2896
|
+
- Forgetting to mark tasks complete
|
|
2897
|
+
- Sequential execution when parallel is possible
|
|
2898
|
+
- Direct tool calls without considering delegation
|
|
2899
|
+
|
|
2900
|
+
## Remember:
|
|
2901
|
+
- You are the **team lead**, not the grunt worker
|
|
2902
|
+
- Your context window is precious - delegate to preserve it
|
|
2903
|
+
- Agents have specialized expertise - USE THEM
|
|
2904
|
+
- TODO tracking gives users visibility into your progress
|
|
2905
|
+
- Parallel execution = faster results
|
|
2906
|
+
`;
|
|
2829
2907
|
// src/hooks/todo-continuation-enforcer.ts
|
|
2830
2908
|
var CONTINUATION_PROMPT = `[SYSTEM REMINDER - TODO CONTINUATION]
|
|
2831
2909
|
|
|
@@ -6783,6 +6861,156 @@ function createUltraworkModeHook() {
|
|
|
6783
6861
|
}
|
|
6784
6862
|
};
|
|
6785
6863
|
}
|
|
6864
|
+
// src/hooks/agent-usage-reminder/storage.ts
|
|
6865
|
+
import {
|
|
6866
|
+
existsSync as existsSync19,
|
|
6867
|
+
mkdirSync as mkdirSync8,
|
|
6868
|
+
readFileSync as readFileSync11,
|
|
6869
|
+
writeFileSync as writeFileSync7,
|
|
6870
|
+
unlinkSync as unlinkSync8
|
|
6871
|
+
} from "fs";
|
|
6872
|
+
import { join as join25 } from "path";
|
|
6873
|
+
|
|
6874
|
+
// src/hooks/agent-usage-reminder/constants.ts
|
|
6875
|
+
import { join as join24 } from "path";
|
|
6876
|
+
var OPENCODE_STORAGE6 = join24(xdgData ?? "", "opencode", "storage");
|
|
6877
|
+
var AGENT_USAGE_REMINDER_STORAGE = join24(OPENCODE_STORAGE6, "agent-usage-reminder");
|
|
6878
|
+
var TARGET_TOOLS = new Set([
|
|
6879
|
+
"grep",
|
|
6880
|
+
"safe_grep",
|
|
6881
|
+
"glob",
|
|
6882
|
+
"safe_glob",
|
|
6883
|
+
"webfetch",
|
|
6884
|
+
"context7_resolve-library-id",
|
|
6885
|
+
"context7_get-library-docs",
|
|
6886
|
+
"websearch_exa_web_search_exa",
|
|
6887
|
+
"grep_app_searchgithub"
|
|
6888
|
+
]);
|
|
6889
|
+
var AGENT_TOOLS = new Set([
|
|
6890
|
+
"task",
|
|
6891
|
+
"call_omo_agent",
|
|
6892
|
+
"background_task"
|
|
6893
|
+
]);
|
|
6894
|
+
var REMINDER_MESSAGE = `
|
|
6895
|
+
[Agent Usage Reminder]
|
|
6896
|
+
|
|
6897
|
+
You called a search/fetch tool directly without leveraging specialized agents.
|
|
6898
|
+
|
|
6899
|
+
RECOMMENDED: Use background_task with explore/librarian agents for better results:
|
|
6900
|
+
|
|
6901
|
+
\`\`\`
|
|
6902
|
+
// Parallel exploration - fire multiple agents simultaneously
|
|
6903
|
+
background_task(agent="explore", prompt="Find all files matching pattern X")
|
|
6904
|
+
background_task(agent="explore", prompt="Search for implementation of Y")
|
|
6905
|
+
background_task(agent="librarian", prompt="Lookup documentation for Z")
|
|
6906
|
+
|
|
6907
|
+
// Then continue your work while they run in background
|
|
6908
|
+
// System will notify you when each completes
|
|
6909
|
+
\`\`\`
|
|
6910
|
+
|
|
6911
|
+
WHY:
|
|
6912
|
+
- Agents can perform deeper, more thorough searches
|
|
6913
|
+
- Background tasks run in parallel, saving time
|
|
6914
|
+
- Specialized agents have domain expertise
|
|
6915
|
+
- Reduces context window usage in main session
|
|
6916
|
+
|
|
6917
|
+
ALWAYS prefer: Multiple parallel background_task calls > Direct tool calls
|
|
6918
|
+
`;
|
|
6919
|
+
|
|
6920
|
+
// src/hooks/agent-usage-reminder/storage.ts
|
|
6921
|
+
function getStoragePath4(sessionID) {
|
|
6922
|
+
return join25(AGENT_USAGE_REMINDER_STORAGE, `${sessionID}.json`);
|
|
6923
|
+
}
|
|
6924
|
+
function loadAgentUsageState(sessionID) {
|
|
6925
|
+
const filePath = getStoragePath4(sessionID);
|
|
6926
|
+
if (!existsSync19(filePath))
|
|
6927
|
+
return null;
|
|
6928
|
+
try {
|
|
6929
|
+
const content = readFileSync11(filePath, "utf-8");
|
|
6930
|
+
return JSON.parse(content);
|
|
6931
|
+
} catch {
|
|
6932
|
+
return null;
|
|
6933
|
+
}
|
|
6934
|
+
}
|
|
6935
|
+
function saveAgentUsageState(state) {
|
|
6936
|
+
if (!existsSync19(AGENT_USAGE_REMINDER_STORAGE)) {
|
|
6937
|
+
mkdirSync8(AGENT_USAGE_REMINDER_STORAGE, { recursive: true });
|
|
6938
|
+
}
|
|
6939
|
+
const filePath = getStoragePath4(state.sessionID);
|
|
6940
|
+
writeFileSync7(filePath, JSON.stringify(state, null, 2));
|
|
6941
|
+
}
|
|
6942
|
+
function clearAgentUsageState(sessionID) {
|
|
6943
|
+
const filePath = getStoragePath4(sessionID);
|
|
6944
|
+
if (existsSync19(filePath)) {
|
|
6945
|
+
unlinkSync8(filePath);
|
|
6946
|
+
}
|
|
6947
|
+
}
|
|
6948
|
+
|
|
6949
|
+
// src/hooks/agent-usage-reminder/index.ts
|
|
6950
|
+
function createAgentUsageReminderHook(_ctx) {
|
|
6951
|
+
const sessionStates = new Map;
|
|
6952
|
+
function getOrCreateState(sessionID) {
|
|
6953
|
+
if (!sessionStates.has(sessionID)) {
|
|
6954
|
+
const persisted = loadAgentUsageState(sessionID);
|
|
6955
|
+
const state = persisted ?? {
|
|
6956
|
+
sessionID,
|
|
6957
|
+
agentUsed: false,
|
|
6958
|
+
reminderCount: 0,
|
|
6959
|
+
updatedAt: Date.now()
|
|
6960
|
+
};
|
|
6961
|
+
sessionStates.set(sessionID, state);
|
|
6962
|
+
}
|
|
6963
|
+
return sessionStates.get(sessionID);
|
|
6964
|
+
}
|
|
6965
|
+
function markAgentUsed(sessionID) {
|
|
6966
|
+
const state = getOrCreateState(sessionID);
|
|
6967
|
+
state.agentUsed = true;
|
|
6968
|
+
state.updatedAt = Date.now();
|
|
6969
|
+
saveAgentUsageState(state);
|
|
6970
|
+
}
|
|
6971
|
+
function resetState(sessionID) {
|
|
6972
|
+
sessionStates.delete(sessionID);
|
|
6973
|
+
clearAgentUsageState(sessionID);
|
|
6974
|
+
}
|
|
6975
|
+
const toolExecuteAfter = async (input, output) => {
|
|
6976
|
+
const { tool, sessionID } = input;
|
|
6977
|
+
const toolLower = tool.toLowerCase();
|
|
6978
|
+
if (AGENT_TOOLS.has(toolLower)) {
|
|
6979
|
+
markAgentUsed(sessionID);
|
|
6980
|
+
return;
|
|
6981
|
+
}
|
|
6982
|
+
if (!TARGET_TOOLS.has(toolLower)) {
|
|
6983
|
+
return;
|
|
6984
|
+
}
|
|
6985
|
+
const state = getOrCreateState(sessionID);
|
|
6986
|
+
if (state.agentUsed) {
|
|
6987
|
+
return;
|
|
6988
|
+
}
|
|
6989
|
+
output.output += REMINDER_MESSAGE;
|
|
6990
|
+
state.reminderCount++;
|
|
6991
|
+
state.updatedAt = Date.now();
|
|
6992
|
+
saveAgentUsageState(state);
|
|
6993
|
+
};
|
|
6994
|
+
const eventHandler = async ({ event }) => {
|
|
6995
|
+
const props = event.properties;
|
|
6996
|
+
if (event.type === "session.deleted") {
|
|
6997
|
+
const sessionInfo = props?.info;
|
|
6998
|
+
if (sessionInfo?.id) {
|
|
6999
|
+
resetState(sessionInfo.id);
|
|
7000
|
+
}
|
|
7001
|
+
}
|
|
7002
|
+
if (event.type === "session.compacted") {
|
|
7003
|
+
const sessionID = props?.sessionID ?? props?.info?.id;
|
|
7004
|
+
if (sessionID) {
|
|
7005
|
+
resetState(sessionID);
|
|
7006
|
+
}
|
|
7007
|
+
}
|
|
7008
|
+
};
|
|
7009
|
+
return {
|
|
7010
|
+
"tool.execute.after": toolExecuteAfter,
|
|
7011
|
+
event: eventHandler
|
|
7012
|
+
};
|
|
7013
|
+
}
|
|
6786
7014
|
// src/auth/antigravity/constants.ts
|
|
6787
7015
|
var ANTIGRAVITY_CLIENT_ID = "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com";
|
|
6788
7016
|
var ANTIGRAVITY_CLIENT_SECRET = "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";
|
|
@@ -8289,11 +8517,11 @@ async function createGoogleAntigravityAuthPlugin({
|
|
|
8289
8517
|
};
|
|
8290
8518
|
}
|
|
8291
8519
|
// src/features/claude-code-command-loader/loader.ts
|
|
8292
|
-
import { existsSync as
|
|
8520
|
+
import { existsSync as existsSync20, readdirSync as readdirSync4, readFileSync as readFileSync12 } from "fs";
|
|
8293
8521
|
import { homedir as homedir9 } from "os";
|
|
8294
|
-
import { join as
|
|
8522
|
+
import { join as join26, basename } from "path";
|
|
8295
8523
|
function loadCommandsFromDir(commandsDir, scope) {
|
|
8296
|
-
if (!
|
|
8524
|
+
if (!existsSync20(commandsDir)) {
|
|
8297
8525
|
return [];
|
|
8298
8526
|
}
|
|
8299
8527
|
const entries = readdirSync4(commandsDir, { withFileTypes: true });
|
|
@@ -8301,10 +8529,10 @@ function loadCommandsFromDir(commandsDir, scope) {
|
|
|
8301
8529
|
for (const entry of entries) {
|
|
8302
8530
|
if (!isMarkdownFile(entry))
|
|
8303
8531
|
continue;
|
|
8304
|
-
const commandPath =
|
|
8532
|
+
const commandPath = join26(commandsDir, entry.name);
|
|
8305
8533
|
const commandName = basename(entry.name, ".md");
|
|
8306
8534
|
try {
|
|
8307
|
-
const content =
|
|
8535
|
+
const content = readFileSync12(commandPath, "utf-8");
|
|
8308
8536
|
const { data, body } = parseFrontmatter(content);
|
|
8309
8537
|
const wrappedTemplate = `<command-instruction>
|
|
8310
8538
|
${body.trim()}
|
|
@@ -8343,31 +8571,31 @@ function commandsToRecord(commands) {
|
|
|
8343
8571
|
return result;
|
|
8344
8572
|
}
|
|
8345
8573
|
function loadUserCommands() {
|
|
8346
|
-
const userCommandsDir =
|
|
8574
|
+
const userCommandsDir = join26(homedir9(), ".claude", "commands");
|
|
8347
8575
|
const commands = loadCommandsFromDir(userCommandsDir, "user");
|
|
8348
8576
|
return commandsToRecord(commands);
|
|
8349
8577
|
}
|
|
8350
8578
|
function loadProjectCommands() {
|
|
8351
|
-
const projectCommandsDir =
|
|
8579
|
+
const projectCommandsDir = join26(process.cwd(), ".claude", "commands");
|
|
8352
8580
|
const commands = loadCommandsFromDir(projectCommandsDir, "project");
|
|
8353
8581
|
return commandsToRecord(commands);
|
|
8354
8582
|
}
|
|
8355
8583
|
function loadOpencodeGlobalCommands() {
|
|
8356
|
-
const opencodeCommandsDir =
|
|
8584
|
+
const opencodeCommandsDir = join26(homedir9(), ".config", "opencode", "command");
|
|
8357
8585
|
const commands = loadCommandsFromDir(opencodeCommandsDir, "opencode");
|
|
8358
8586
|
return commandsToRecord(commands);
|
|
8359
8587
|
}
|
|
8360
8588
|
function loadOpencodeProjectCommands() {
|
|
8361
|
-
const opencodeProjectDir =
|
|
8589
|
+
const opencodeProjectDir = join26(process.cwd(), ".opencode", "command");
|
|
8362
8590
|
const commands = loadCommandsFromDir(opencodeProjectDir, "opencode-project");
|
|
8363
8591
|
return commandsToRecord(commands);
|
|
8364
8592
|
}
|
|
8365
8593
|
// src/features/claude-code-skill-loader/loader.ts
|
|
8366
|
-
import { existsSync as
|
|
8594
|
+
import { existsSync as existsSync21, readdirSync as readdirSync5, readFileSync as readFileSync13 } from "fs";
|
|
8367
8595
|
import { homedir as homedir10 } from "os";
|
|
8368
|
-
import { join as
|
|
8596
|
+
import { join as join27 } from "path";
|
|
8369
8597
|
function loadSkillsFromDir(skillsDir, scope) {
|
|
8370
|
-
if (!
|
|
8598
|
+
if (!existsSync21(skillsDir)) {
|
|
8371
8599
|
return [];
|
|
8372
8600
|
}
|
|
8373
8601
|
const entries = readdirSync5(skillsDir, { withFileTypes: true });
|
|
@@ -8375,15 +8603,15 @@ function loadSkillsFromDir(skillsDir, scope) {
|
|
|
8375
8603
|
for (const entry of entries) {
|
|
8376
8604
|
if (entry.name.startsWith("."))
|
|
8377
8605
|
continue;
|
|
8378
|
-
const skillPath =
|
|
8606
|
+
const skillPath = join27(skillsDir, entry.name);
|
|
8379
8607
|
if (!entry.isDirectory() && !entry.isSymbolicLink())
|
|
8380
8608
|
continue;
|
|
8381
8609
|
const resolvedPath = resolveSymlink(skillPath);
|
|
8382
|
-
const skillMdPath =
|
|
8383
|
-
if (!
|
|
8610
|
+
const skillMdPath = join27(resolvedPath, "SKILL.md");
|
|
8611
|
+
if (!existsSync21(skillMdPath))
|
|
8384
8612
|
continue;
|
|
8385
8613
|
try {
|
|
8386
|
-
const content =
|
|
8614
|
+
const content = readFileSync13(skillMdPath, "utf-8");
|
|
8387
8615
|
const { data, body } = parseFrontmatter(content);
|
|
8388
8616
|
const skillName = data.name || entry.name;
|
|
8389
8617
|
const originalDescription = data.description || "";
|
|
@@ -8414,7 +8642,7 @@ $ARGUMENTS
|
|
|
8414
8642
|
return skills;
|
|
8415
8643
|
}
|
|
8416
8644
|
function loadUserSkillsAsCommands() {
|
|
8417
|
-
const userSkillsDir =
|
|
8645
|
+
const userSkillsDir = join27(homedir10(), ".claude", "skills");
|
|
8418
8646
|
const skills = loadSkillsFromDir(userSkillsDir, "user");
|
|
8419
8647
|
return skills.reduce((acc, skill) => {
|
|
8420
8648
|
acc[skill.name] = skill.definition;
|
|
@@ -8422,7 +8650,7 @@ function loadUserSkillsAsCommands() {
|
|
|
8422
8650
|
}, {});
|
|
8423
8651
|
}
|
|
8424
8652
|
function loadProjectSkillsAsCommands() {
|
|
8425
|
-
const projectSkillsDir =
|
|
8653
|
+
const projectSkillsDir = join27(process.cwd(), ".claude", "skills");
|
|
8426
8654
|
const skills = loadSkillsFromDir(projectSkillsDir, "project");
|
|
8427
8655
|
return skills.reduce((acc, skill) => {
|
|
8428
8656
|
acc[skill.name] = skill.definition;
|
|
@@ -8430,9 +8658,9 @@ function loadProjectSkillsAsCommands() {
|
|
|
8430
8658
|
}, {});
|
|
8431
8659
|
}
|
|
8432
8660
|
// src/features/claude-code-agent-loader/loader.ts
|
|
8433
|
-
import { existsSync as
|
|
8661
|
+
import { existsSync as existsSync22, readdirSync as readdirSync6, readFileSync as readFileSync14 } from "fs";
|
|
8434
8662
|
import { homedir as homedir11 } from "os";
|
|
8435
|
-
import { join as
|
|
8663
|
+
import { join as join28, basename as basename2 } from "path";
|
|
8436
8664
|
function parseToolsConfig(toolsStr) {
|
|
8437
8665
|
if (!toolsStr)
|
|
8438
8666
|
return;
|
|
@@ -8446,7 +8674,7 @@ function parseToolsConfig(toolsStr) {
|
|
|
8446
8674
|
return result;
|
|
8447
8675
|
}
|
|
8448
8676
|
function loadAgentsFromDir(agentsDir, scope) {
|
|
8449
|
-
if (!
|
|
8677
|
+
if (!existsSync22(agentsDir)) {
|
|
8450
8678
|
return [];
|
|
8451
8679
|
}
|
|
8452
8680
|
const entries = readdirSync6(agentsDir, { withFileTypes: true });
|
|
@@ -8454,10 +8682,10 @@ function loadAgentsFromDir(agentsDir, scope) {
|
|
|
8454
8682
|
for (const entry of entries) {
|
|
8455
8683
|
if (!isMarkdownFile(entry))
|
|
8456
8684
|
continue;
|
|
8457
|
-
const agentPath =
|
|
8685
|
+
const agentPath = join28(agentsDir, entry.name);
|
|
8458
8686
|
const agentName = basename2(entry.name, ".md");
|
|
8459
8687
|
try {
|
|
8460
|
-
const content =
|
|
8688
|
+
const content = readFileSync14(agentPath, "utf-8");
|
|
8461
8689
|
const { data, body } = parseFrontmatter(content);
|
|
8462
8690
|
const name = data.name || agentName;
|
|
8463
8691
|
const originalDescription = data.description || "";
|
|
@@ -8484,7 +8712,7 @@ function loadAgentsFromDir(agentsDir, scope) {
|
|
|
8484
8712
|
return agents;
|
|
8485
8713
|
}
|
|
8486
8714
|
function loadUserAgents() {
|
|
8487
|
-
const userAgentsDir =
|
|
8715
|
+
const userAgentsDir = join28(homedir11(), ".claude", "agents");
|
|
8488
8716
|
const agents = loadAgentsFromDir(userAgentsDir, "user");
|
|
8489
8717
|
const result = {};
|
|
8490
8718
|
for (const agent of agents) {
|
|
@@ -8493,7 +8721,7 @@ function loadUserAgents() {
|
|
|
8493
8721
|
return result;
|
|
8494
8722
|
}
|
|
8495
8723
|
function loadProjectAgents() {
|
|
8496
|
-
const projectAgentsDir =
|
|
8724
|
+
const projectAgentsDir = join28(process.cwd(), ".claude", "agents");
|
|
8497
8725
|
const agents = loadAgentsFromDir(projectAgentsDir, "project");
|
|
8498
8726
|
const result = {};
|
|
8499
8727
|
for (const agent of agents) {
|
|
@@ -8502,9 +8730,9 @@ function loadProjectAgents() {
|
|
|
8502
8730
|
return result;
|
|
8503
8731
|
}
|
|
8504
8732
|
// src/features/claude-code-mcp-loader/loader.ts
|
|
8505
|
-
import { existsSync as
|
|
8733
|
+
import { existsSync as existsSync23 } from "fs";
|
|
8506
8734
|
import { homedir as homedir12 } from "os";
|
|
8507
|
-
import { join as
|
|
8735
|
+
import { join as join29 } from "path";
|
|
8508
8736
|
|
|
8509
8737
|
// src/features/claude-code-mcp-loader/env-expander.ts
|
|
8510
8738
|
function expandEnvVars(value) {
|
|
@@ -8573,13 +8801,13 @@ function getMcpConfigPaths() {
|
|
|
8573
8801
|
const home = homedir12();
|
|
8574
8802
|
const cwd = process.cwd();
|
|
8575
8803
|
return [
|
|
8576
|
-
{ path:
|
|
8577
|
-
{ path:
|
|
8578
|
-
{ path:
|
|
8804
|
+
{ path: join29(home, ".claude", ".mcp.json"), scope: "user" },
|
|
8805
|
+
{ path: join29(cwd, ".mcp.json"), scope: "project" },
|
|
8806
|
+
{ path: join29(cwd, ".claude", ".mcp.json"), scope: "local" }
|
|
8579
8807
|
];
|
|
8580
8808
|
}
|
|
8581
8809
|
async function loadMcpConfigFile(filePath) {
|
|
8582
|
-
if (!
|
|
8810
|
+
if (!existsSync23(filePath)) {
|
|
8583
8811
|
return null;
|
|
8584
8812
|
}
|
|
8585
8813
|
try {
|
|
@@ -8865,14 +9093,14 @@ var EXT_TO_LANG = {
|
|
|
8865
9093
|
".tfvars": "terraform"
|
|
8866
9094
|
};
|
|
8867
9095
|
// src/tools/lsp/config.ts
|
|
8868
|
-
import { existsSync as
|
|
8869
|
-
import { join as
|
|
9096
|
+
import { existsSync as existsSync24, readFileSync as readFileSync15 } from "fs";
|
|
9097
|
+
import { join as join30 } from "path";
|
|
8870
9098
|
import { homedir as homedir13 } from "os";
|
|
8871
9099
|
function loadJsonFile(path5) {
|
|
8872
|
-
if (!
|
|
9100
|
+
if (!existsSync24(path5))
|
|
8873
9101
|
return null;
|
|
8874
9102
|
try {
|
|
8875
|
-
return JSON.parse(
|
|
9103
|
+
return JSON.parse(readFileSync15(path5, "utf-8"));
|
|
8876
9104
|
} catch {
|
|
8877
9105
|
return null;
|
|
8878
9106
|
}
|
|
@@ -8880,9 +9108,9 @@ function loadJsonFile(path5) {
|
|
|
8880
9108
|
function getConfigPaths() {
|
|
8881
9109
|
const cwd = process.cwd();
|
|
8882
9110
|
return {
|
|
8883
|
-
project:
|
|
8884
|
-
user:
|
|
8885
|
-
opencode:
|
|
9111
|
+
project: join30(cwd, ".opencode", "oh-my-opencode.json"),
|
|
9112
|
+
user: join30(homedir13(), ".config", "opencode", "oh-my-opencode.json"),
|
|
9113
|
+
opencode: join30(homedir13(), ".config", "opencode", "opencode.json")
|
|
8886
9114
|
};
|
|
8887
9115
|
}
|
|
8888
9116
|
function loadAllConfigs() {
|
|
@@ -8975,7 +9203,7 @@ function isServerInstalled(command) {
|
|
|
8975
9203
|
const pathEnv = process.env.PATH || "";
|
|
8976
9204
|
const paths = pathEnv.split(":");
|
|
8977
9205
|
for (const p of paths) {
|
|
8978
|
-
if (
|
|
9206
|
+
if (existsSync24(join30(p, cmd))) {
|
|
8979
9207
|
return true;
|
|
8980
9208
|
}
|
|
8981
9209
|
}
|
|
@@ -9025,7 +9253,7 @@ function getAllServers() {
|
|
|
9025
9253
|
}
|
|
9026
9254
|
// src/tools/lsp/client.ts
|
|
9027
9255
|
var {spawn: spawn4 } = globalThis.Bun;
|
|
9028
|
-
import { readFileSync as
|
|
9256
|
+
import { readFileSync as readFileSync16 } from "fs";
|
|
9029
9257
|
import { extname, resolve as resolve5 } from "path";
|
|
9030
9258
|
class LSPServerManager {
|
|
9031
9259
|
static instance;
|
|
@@ -9425,7 +9653,7 @@ ${msg}`);
|
|
|
9425
9653
|
const absPath = resolve5(filePath);
|
|
9426
9654
|
if (this.openedFiles.has(absPath))
|
|
9427
9655
|
return;
|
|
9428
|
-
const text =
|
|
9656
|
+
const text = readFileSync16(absPath, "utf-8");
|
|
9429
9657
|
const ext = extname(absPath);
|
|
9430
9658
|
const languageId = getLanguageId(ext);
|
|
9431
9659
|
this.notify("textDocument/didOpen", {
|
|
@@ -9540,16 +9768,16 @@ ${msg}`);
|
|
|
9540
9768
|
}
|
|
9541
9769
|
// src/tools/lsp/utils.ts
|
|
9542
9770
|
import { extname as extname2, resolve as resolve6 } from "path";
|
|
9543
|
-
import { existsSync as
|
|
9771
|
+
import { existsSync as existsSync25, readFileSync as readFileSync17, writeFileSync as writeFileSync8 } from "fs";
|
|
9544
9772
|
function findWorkspaceRoot(filePath) {
|
|
9545
9773
|
let dir = resolve6(filePath);
|
|
9546
|
-
if (!
|
|
9774
|
+
if (!existsSync25(dir) || !__require("fs").statSync(dir).isDirectory()) {
|
|
9547
9775
|
dir = __require("path").dirname(dir);
|
|
9548
9776
|
}
|
|
9549
9777
|
const markers = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
9550
9778
|
while (dir !== "/") {
|
|
9551
9779
|
for (const marker of markers) {
|
|
9552
|
-
if (
|
|
9780
|
+
if (existsSync25(__require("path").join(dir, marker))) {
|
|
9553
9781
|
return dir;
|
|
9554
9782
|
}
|
|
9555
9783
|
}
|
|
@@ -9707,7 +9935,7 @@ function formatCodeActions(actions) {
|
|
|
9707
9935
|
}
|
|
9708
9936
|
function applyTextEditsToFile(filePath, edits) {
|
|
9709
9937
|
try {
|
|
9710
|
-
let content =
|
|
9938
|
+
let content = readFileSync17(filePath, "utf-8");
|
|
9711
9939
|
const lines = content.split(`
|
|
9712
9940
|
`);
|
|
9713
9941
|
const sortedEdits = [...edits].sort((a, b) => {
|
|
@@ -9732,7 +9960,7 @@ function applyTextEditsToFile(filePath, edits) {
|
|
|
9732
9960
|
`));
|
|
9733
9961
|
}
|
|
9734
9962
|
}
|
|
9735
|
-
|
|
9963
|
+
writeFileSync8(filePath, lines.join(`
|
|
9736
9964
|
`), "utf-8");
|
|
9737
9965
|
return { success: true, editCount: edits.length };
|
|
9738
9966
|
} catch (err) {
|
|
@@ -9763,7 +9991,7 @@ function applyWorkspaceEdit(edit) {
|
|
|
9763
9991
|
if (change.kind === "create") {
|
|
9764
9992
|
try {
|
|
9765
9993
|
const filePath = change.uri.replace("file://", "");
|
|
9766
|
-
|
|
9994
|
+
writeFileSync8(filePath, "", "utf-8");
|
|
9767
9995
|
result.filesModified.push(filePath);
|
|
9768
9996
|
} catch (err) {
|
|
9769
9997
|
result.success = false;
|
|
@@ -9773,8 +10001,8 @@ function applyWorkspaceEdit(edit) {
|
|
|
9773
10001
|
try {
|
|
9774
10002
|
const oldPath = change.oldUri.replace("file://", "");
|
|
9775
10003
|
const newPath = change.newUri.replace("file://", "");
|
|
9776
|
-
const content =
|
|
9777
|
-
|
|
10004
|
+
const content = readFileSync17(oldPath, "utf-8");
|
|
10005
|
+
writeFileSync8(newPath, content, "utf-8");
|
|
9778
10006
|
__require("fs").unlinkSync(oldPath);
|
|
9779
10007
|
result.filesModified.push(newPath);
|
|
9780
10008
|
} catch (err) {
|
|
@@ -22474,13 +22702,13 @@ var lsp_code_action_resolve = tool({
|
|
|
22474
22702
|
});
|
|
22475
22703
|
// src/tools/ast-grep/constants.ts
|
|
22476
22704
|
import { createRequire as createRequire4 } from "module";
|
|
22477
|
-
import { dirname as dirname5, join as
|
|
22478
|
-
import { existsSync as
|
|
22705
|
+
import { dirname as dirname5, join as join32 } from "path";
|
|
22706
|
+
import { existsSync as existsSync27, statSync as statSync3 } from "fs";
|
|
22479
22707
|
|
|
22480
22708
|
// src/tools/ast-grep/downloader.ts
|
|
22481
22709
|
var {spawn: spawn5 } = globalThis.Bun;
|
|
22482
|
-
import { existsSync as
|
|
22483
|
-
import { join as
|
|
22710
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync9, chmodSync as chmodSync2, unlinkSync as unlinkSync9 } from "fs";
|
|
22711
|
+
import { join as join31 } from "path";
|
|
22484
22712
|
import { homedir as homedir14 } from "os";
|
|
22485
22713
|
import { createRequire as createRequire3 } from "module";
|
|
22486
22714
|
var REPO2 = "ast-grep/ast-grep";
|
|
@@ -22506,19 +22734,19 @@ var PLATFORM_MAP2 = {
|
|
|
22506
22734
|
function getCacheDir3() {
|
|
22507
22735
|
if (process.platform === "win32") {
|
|
22508
22736
|
const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA;
|
|
22509
|
-
const base2 = localAppData ||
|
|
22510
|
-
return
|
|
22737
|
+
const base2 = localAppData || join31(homedir14(), "AppData", "Local");
|
|
22738
|
+
return join31(base2, "oh-my-opencode", "bin");
|
|
22511
22739
|
}
|
|
22512
22740
|
const xdgCache2 = process.env.XDG_CACHE_HOME;
|
|
22513
|
-
const base = xdgCache2 ||
|
|
22514
|
-
return
|
|
22741
|
+
const base = xdgCache2 || join31(homedir14(), ".cache");
|
|
22742
|
+
return join31(base, "oh-my-opencode", "bin");
|
|
22515
22743
|
}
|
|
22516
22744
|
function getBinaryName3() {
|
|
22517
22745
|
return process.platform === "win32" ? "sg.exe" : "sg";
|
|
22518
22746
|
}
|
|
22519
22747
|
function getCachedBinaryPath2() {
|
|
22520
|
-
const binaryPath =
|
|
22521
|
-
return
|
|
22748
|
+
const binaryPath = join31(getCacheDir3(), getBinaryName3());
|
|
22749
|
+
return existsSync26(binaryPath) ? binaryPath : null;
|
|
22522
22750
|
}
|
|
22523
22751
|
async function extractZip2(archivePath, destDir) {
|
|
22524
22752
|
const proc = process.platform === "win32" ? spawn5([
|
|
@@ -22544,8 +22772,8 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
|
22544
22772
|
}
|
|
22545
22773
|
const cacheDir = getCacheDir3();
|
|
22546
22774
|
const binaryName = getBinaryName3();
|
|
22547
|
-
const binaryPath =
|
|
22548
|
-
if (
|
|
22775
|
+
const binaryPath = join31(cacheDir, binaryName);
|
|
22776
|
+
if (existsSync26(binaryPath)) {
|
|
22549
22777
|
return binaryPath;
|
|
22550
22778
|
}
|
|
22551
22779
|
const { arch, os: os4 } = platformInfo;
|
|
@@ -22553,21 +22781,21 @@ async function downloadAstGrep(version2 = DEFAULT_VERSION) {
|
|
|
22553
22781
|
const downloadUrl = `https://github.com/${REPO2}/releases/download/${version2}/${assetName}`;
|
|
22554
22782
|
console.log(`[oh-my-opencode] Downloading ast-grep binary...`);
|
|
22555
22783
|
try {
|
|
22556
|
-
if (!
|
|
22557
|
-
|
|
22784
|
+
if (!existsSync26(cacheDir)) {
|
|
22785
|
+
mkdirSync9(cacheDir, { recursive: true });
|
|
22558
22786
|
}
|
|
22559
22787
|
const response2 = await fetch(downloadUrl, { redirect: "follow" });
|
|
22560
22788
|
if (!response2.ok) {
|
|
22561
22789
|
throw new Error(`HTTP ${response2.status}: ${response2.statusText}`);
|
|
22562
22790
|
}
|
|
22563
|
-
const archivePath =
|
|
22791
|
+
const archivePath = join31(cacheDir, assetName);
|
|
22564
22792
|
const arrayBuffer = await response2.arrayBuffer();
|
|
22565
22793
|
await Bun.write(archivePath, arrayBuffer);
|
|
22566
22794
|
await extractZip2(archivePath, cacheDir);
|
|
22567
|
-
if (
|
|
22568
|
-
|
|
22795
|
+
if (existsSync26(archivePath)) {
|
|
22796
|
+
unlinkSync9(archivePath);
|
|
22569
22797
|
}
|
|
22570
|
-
if (process.platform !== "win32" &&
|
|
22798
|
+
if (process.platform !== "win32" && existsSync26(binaryPath)) {
|
|
22571
22799
|
chmodSync2(binaryPath, 493);
|
|
22572
22800
|
}
|
|
22573
22801
|
console.log(`[oh-my-opencode] ast-grep binary ready.`);
|
|
@@ -22618,8 +22846,8 @@ function findSgCliPathSync() {
|
|
|
22618
22846
|
const require2 = createRequire4(import.meta.url);
|
|
22619
22847
|
const cliPkgPath = require2.resolve("@ast-grep/cli/package.json");
|
|
22620
22848
|
const cliDir = dirname5(cliPkgPath);
|
|
22621
|
-
const sgPath =
|
|
22622
|
-
if (
|
|
22849
|
+
const sgPath = join32(cliDir, binaryName);
|
|
22850
|
+
if (existsSync27(sgPath) && isValidBinary(sgPath)) {
|
|
22623
22851
|
return sgPath;
|
|
22624
22852
|
}
|
|
22625
22853
|
} catch {}
|
|
@@ -22630,8 +22858,8 @@ function findSgCliPathSync() {
|
|
|
22630
22858
|
const pkgPath = require2.resolve(`${platformPkg}/package.json`);
|
|
22631
22859
|
const pkgDir = dirname5(pkgPath);
|
|
22632
22860
|
const astGrepName = process.platform === "win32" ? "ast-grep.exe" : "ast-grep";
|
|
22633
|
-
const binaryPath =
|
|
22634
|
-
if (
|
|
22861
|
+
const binaryPath = join32(pkgDir, astGrepName);
|
|
22862
|
+
if (existsSync27(binaryPath) && isValidBinary(binaryPath)) {
|
|
22635
22863
|
return binaryPath;
|
|
22636
22864
|
}
|
|
22637
22865
|
} catch {}
|
|
@@ -22639,7 +22867,7 @@ function findSgCliPathSync() {
|
|
|
22639
22867
|
if (process.platform === "darwin") {
|
|
22640
22868
|
const homebrewPaths = ["/opt/homebrew/bin/sg", "/usr/local/bin/sg"];
|
|
22641
22869
|
for (const path5 of homebrewPaths) {
|
|
22642
|
-
if (
|
|
22870
|
+
if (existsSync27(path5) && isValidBinary(path5)) {
|
|
22643
22871
|
return path5;
|
|
22644
22872
|
}
|
|
22645
22873
|
}
|
|
@@ -22695,11 +22923,11 @@ var DEFAULT_MAX_MATCHES = 500;
|
|
|
22695
22923
|
|
|
22696
22924
|
// src/tools/ast-grep/cli.ts
|
|
22697
22925
|
var {spawn: spawn6 } = globalThis.Bun;
|
|
22698
|
-
import { existsSync as
|
|
22926
|
+
import { existsSync as existsSync28 } from "fs";
|
|
22699
22927
|
var resolvedCliPath3 = null;
|
|
22700
22928
|
var initPromise2 = null;
|
|
22701
22929
|
async function getAstGrepPath() {
|
|
22702
|
-
if (resolvedCliPath3 !== null &&
|
|
22930
|
+
if (resolvedCliPath3 !== null && existsSync28(resolvedCliPath3)) {
|
|
22703
22931
|
return resolvedCliPath3;
|
|
22704
22932
|
}
|
|
22705
22933
|
if (initPromise2) {
|
|
@@ -22707,7 +22935,7 @@ async function getAstGrepPath() {
|
|
|
22707
22935
|
}
|
|
22708
22936
|
initPromise2 = (async () => {
|
|
22709
22937
|
const syncPath = findSgCliPathSync();
|
|
22710
|
-
if (syncPath &&
|
|
22938
|
+
if (syncPath && existsSync28(syncPath)) {
|
|
22711
22939
|
resolvedCliPath3 = syncPath;
|
|
22712
22940
|
setSgCliPath(syncPath);
|
|
22713
22941
|
return syncPath;
|
|
@@ -22741,7 +22969,7 @@ async function runSg(options) {
|
|
|
22741
22969
|
const paths = options.paths && options.paths.length > 0 ? options.paths : ["."];
|
|
22742
22970
|
args.push(...paths);
|
|
22743
22971
|
let cliPath = getSgCliPath();
|
|
22744
|
-
if (!
|
|
22972
|
+
if (!existsSync28(cliPath) && cliPath !== "sg") {
|
|
22745
22973
|
const downloadedPath = await getAstGrepPath();
|
|
22746
22974
|
if (downloadedPath) {
|
|
22747
22975
|
cliPath = downloadedPath;
|
|
@@ -23005,8 +23233,8 @@ var ast_grep_replace = tool({
|
|
|
23005
23233
|
var {spawn: spawn7 } = globalThis.Bun;
|
|
23006
23234
|
|
|
23007
23235
|
// src/tools/grep/constants.ts
|
|
23008
|
-
import { existsSync as
|
|
23009
|
-
import { join as
|
|
23236
|
+
import { existsSync as existsSync29 } from "fs";
|
|
23237
|
+
import { join as join33, dirname as dirname6 } from "path";
|
|
23010
23238
|
import { spawnSync } from "child_process";
|
|
23011
23239
|
var cachedCli = null;
|
|
23012
23240
|
function findExecutable(name) {
|
|
@@ -23027,13 +23255,13 @@ function getOpenCodeBundledRg() {
|
|
|
23027
23255
|
const isWindows = process.platform === "win32";
|
|
23028
23256
|
const rgName = isWindows ? "rg.exe" : "rg";
|
|
23029
23257
|
const candidates = [
|
|
23030
|
-
|
|
23031
|
-
|
|
23032
|
-
|
|
23033
|
-
|
|
23258
|
+
join33(execDir, rgName),
|
|
23259
|
+
join33(execDir, "bin", rgName),
|
|
23260
|
+
join33(execDir, "..", "bin", rgName),
|
|
23261
|
+
join33(execDir, "..", "libexec", rgName)
|
|
23034
23262
|
];
|
|
23035
23263
|
for (const candidate of candidates) {
|
|
23036
|
-
if (
|
|
23264
|
+
if (existsSync29(candidate)) {
|
|
23037
23265
|
return candidate;
|
|
23038
23266
|
}
|
|
23039
23267
|
}
|
|
@@ -23431,11 +23659,11 @@ var glob = tool({
|
|
|
23431
23659
|
}
|
|
23432
23660
|
});
|
|
23433
23661
|
// src/tools/slashcommand/tools.ts
|
|
23434
|
-
import { existsSync as
|
|
23662
|
+
import { existsSync as existsSync30, readdirSync as readdirSync7, readFileSync as readFileSync18 } from "fs";
|
|
23435
23663
|
import { homedir as homedir15 } from "os";
|
|
23436
|
-
import { join as
|
|
23664
|
+
import { join as join34, basename as basename3, dirname as dirname7 } from "path";
|
|
23437
23665
|
function discoverCommandsFromDir(commandsDir, scope) {
|
|
23438
|
-
if (!
|
|
23666
|
+
if (!existsSync30(commandsDir)) {
|
|
23439
23667
|
return [];
|
|
23440
23668
|
}
|
|
23441
23669
|
const entries = readdirSync7(commandsDir, { withFileTypes: true });
|
|
@@ -23443,10 +23671,10 @@ function discoverCommandsFromDir(commandsDir, scope) {
|
|
|
23443
23671
|
for (const entry of entries) {
|
|
23444
23672
|
if (!isMarkdownFile(entry))
|
|
23445
23673
|
continue;
|
|
23446
|
-
const commandPath =
|
|
23674
|
+
const commandPath = join34(commandsDir, entry.name);
|
|
23447
23675
|
const commandName = basename3(entry.name, ".md");
|
|
23448
23676
|
try {
|
|
23449
|
-
const content =
|
|
23677
|
+
const content = readFileSync18(commandPath, "utf-8");
|
|
23450
23678
|
const { data, body } = parseFrontmatter(content);
|
|
23451
23679
|
const metadata = {
|
|
23452
23680
|
name: commandName,
|
|
@@ -23470,10 +23698,10 @@ function discoverCommandsFromDir(commandsDir, scope) {
|
|
|
23470
23698
|
return commands;
|
|
23471
23699
|
}
|
|
23472
23700
|
function discoverCommandsSync() {
|
|
23473
|
-
const userCommandsDir =
|
|
23474
|
-
const projectCommandsDir =
|
|
23475
|
-
const opencodeGlobalDir =
|
|
23476
|
-
const opencodeProjectDir =
|
|
23701
|
+
const userCommandsDir = join34(homedir15(), ".claude", "commands");
|
|
23702
|
+
const projectCommandsDir = join34(process.cwd(), ".claude", "commands");
|
|
23703
|
+
const opencodeGlobalDir = join34(homedir15(), ".config", "opencode", "command");
|
|
23704
|
+
const opencodeProjectDir = join34(process.cwd(), ".opencode", "command");
|
|
23477
23705
|
const userCommands = discoverCommandsFromDir(userCommandsDir, "user");
|
|
23478
23706
|
const opencodeGlobalCommands = discoverCommandsFromDir(opencodeGlobalDir, "opencode");
|
|
23479
23707
|
const projectCommands = discoverCommandsFromDir(projectCommandsDir, "project");
|
|
@@ -23605,9 +23833,9 @@ var SkillFrontmatterSchema = exports_external.object({
|
|
|
23605
23833
|
metadata: exports_external.record(exports_external.string(), exports_external.string()).optional()
|
|
23606
23834
|
});
|
|
23607
23835
|
// src/tools/skill/tools.ts
|
|
23608
|
-
import { existsSync as
|
|
23836
|
+
import { existsSync as existsSync31, readdirSync as readdirSync8, readFileSync as readFileSync19 } from "fs";
|
|
23609
23837
|
import { homedir as homedir16 } from "os";
|
|
23610
|
-
import { join as
|
|
23838
|
+
import { join as join35, basename as basename4 } from "path";
|
|
23611
23839
|
function parseSkillFrontmatter(data) {
|
|
23612
23840
|
return {
|
|
23613
23841
|
name: typeof data.name === "string" ? data.name : "",
|
|
@@ -23618,7 +23846,7 @@ function parseSkillFrontmatter(data) {
|
|
|
23618
23846
|
};
|
|
23619
23847
|
}
|
|
23620
23848
|
function discoverSkillsFromDir(skillsDir, scope) {
|
|
23621
|
-
if (!
|
|
23849
|
+
if (!existsSync31(skillsDir)) {
|
|
23622
23850
|
return [];
|
|
23623
23851
|
}
|
|
23624
23852
|
const entries = readdirSync8(skillsDir, { withFileTypes: true });
|
|
@@ -23626,14 +23854,14 @@ function discoverSkillsFromDir(skillsDir, scope) {
|
|
|
23626
23854
|
for (const entry of entries) {
|
|
23627
23855
|
if (entry.name.startsWith("."))
|
|
23628
23856
|
continue;
|
|
23629
|
-
const skillPath =
|
|
23857
|
+
const skillPath = join35(skillsDir, entry.name);
|
|
23630
23858
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
23631
23859
|
const resolvedPath = resolveSymlink(skillPath);
|
|
23632
|
-
const skillMdPath =
|
|
23633
|
-
if (!
|
|
23860
|
+
const skillMdPath = join35(resolvedPath, "SKILL.md");
|
|
23861
|
+
if (!existsSync31(skillMdPath))
|
|
23634
23862
|
continue;
|
|
23635
23863
|
try {
|
|
23636
|
-
const content =
|
|
23864
|
+
const content = readFileSync19(skillMdPath, "utf-8");
|
|
23637
23865
|
const { data } = parseFrontmatter(content);
|
|
23638
23866
|
skills.push({
|
|
23639
23867
|
name: data.name || entry.name,
|
|
@@ -23648,8 +23876,8 @@ function discoverSkillsFromDir(skillsDir, scope) {
|
|
|
23648
23876
|
return skills;
|
|
23649
23877
|
}
|
|
23650
23878
|
function discoverSkillsSync() {
|
|
23651
|
-
const userSkillsDir =
|
|
23652
|
-
const projectSkillsDir =
|
|
23879
|
+
const userSkillsDir = join35(homedir16(), ".claude", "skills");
|
|
23880
|
+
const projectSkillsDir = join35(process.cwd(), ".claude", "skills");
|
|
23653
23881
|
const userSkills = discoverSkillsFromDir(userSkillsDir, "user");
|
|
23654
23882
|
const projectSkills = discoverSkillsFromDir(projectSkillsDir, "project");
|
|
23655
23883
|
return [...projectSkills, ...userSkills];
|
|
@@ -23659,12 +23887,12 @@ var skillListForDescription = availableSkills.map((s) => `- ${s.name}: ${s.descr
|
|
|
23659
23887
|
`);
|
|
23660
23888
|
async function parseSkillMd(skillPath) {
|
|
23661
23889
|
const resolvedPath = resolveSymlink(skillPath);
|
|
23662
|
-
const skillMdPath =
|
|
23663
|
-
if (!
|
|
23890
|
+
const skillMdPath = join35(resolvedPath, "SKILL.md");
|
|
23891
|
+
if (!existsSync31(skillMdPath)) {
|
|
23664
23892
|
return null;
|
|
23665
23893
|
}
|
|
23666
23894
|
try {
|
|
23667
|
-
let content =
|
|
23895
|
+
let content = readFileSync19(skillMdPath, "utf-8");
|
|
23668
23896
|
content = await resolveCommandsInText(content);
|
|
23669
23897
|
const { data, body } = parseFrontmatter(content);
|
|
23670
23898
|
const frontmatter2 = parseSkillFrontmatter(data);
|
|
@@ -23675,12 +23903,12 @@ async function parseSkillMd(skillPath) {
|
|
|
23675
23903
|
allowedTools: frontmatter2["allowed-tools"],
|
|
23676
23904
|
metadata: frontmatter2.metadata
|
|
23677
23905
|
};
|
|
23678
|
-
const referencesDir =
|
|
23679
|
-
const scriptsDir =
|
|
23680
|
-
const assetsDir =
|
|
23681
|
-
const references =
|
|
23682
|
-
const scripts =
|
|
23683
|
-
const assets =
|
|
23906
|
+
const referencesDir = join35(resolvedPath, "references");
|
|
23907
|
+
const scriptsDir = join35(resolvedPath, "scripts");
|
|
23908
|
+
const assetsDir = join35(resolvedPath, "assets");
|
|
23909
|
+
const references = existsSync31(referencesDir) ? readdirSync8(referencesDir).filter((f) => !f.startsWith(".")) : [];
|
|
23910
|
+
const scripts = existsSync31(scriptsDir) ? readdirSync8(scriptsDir).filter((f) => !f.startsWith(".") && !f.startsWith("__")) : [];
|
|
23911
|
+
const assets = existsSync31(assetsDir) ? readdirSync8(assetsDir).filter((f) => !f.startsWith(".")) : [];
|
|
23684
23912
|
return {
|
|
23685
23913
|
name: metadata.name,
|
|
23686
23914
|
path: resolvedPath,
|
|
@@ -23696,7 +23924,7 @@ async function parseSkillMd(skillPath) {
|
|
|
23696
23924
|
}
|
|
23697
23925
|
}
|
|
23698
23926
|
async function discoverSkillsFromDirAsync(skillsDir) {
|
|
23699
|
-
if (!
|
|
23927
|
+
if (!existsSync31(skillsDir)) {
|
|
23700
23928
|
return [];
|
|
23701
23929
|
}
|
|
23702
23930
|
const entries = readdirSync8(skillsDir, { withFileTypes: true });
|
|
@@ -23704,7 +23932,7 @@ async function discoverSkillsFromDirAsync(skillsDir) {
|
|
|
23704
23932
|
for (const entry of entries) {
|
|
23705
23933
|
if (entry.name.startsWith("."))
|
|
23706
23934
|
continue;
|
|
23707
|
-
const skillPath =
|
|
23935
|
+
const skillPath = join35(skillsDir, entry.name);
|
|
23708
23936
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
23709
23937
|
const skillInfo = await parseSkillMd(skillPath);
|
|
23710
23938
|
if (skillInfo) {
|
|
@@ -23715,8 +23943,8 @@ async function discoverSkillsFromDirAsync(skillsDir) {
|
|
|
23715
23943
|
return skills;
|
|
23716
23944
|
}
|
|
23717
23945
|
async function discoverSkills() {
|
|
23718
|
-
const userSkillsDir =
|
|
23719
|
-
const projectSkillsDir =
|
|
23946
|
+
const userSkillsDir = join35(homedir16(), ".claude", "skills");
|
|
23947
|
+
const projectSkillsDir = join35(process.cwd(), ".claude", "skills");
|
|
23720
23948
|
const userSkills = await discoverSkillsFromDirAsync(userSkillsDir);
|
|
23721
23949
|
const projectSkills = await discoverSkillsFromDirAsync(projectSkillsDir);
|
|
23722
23950
|
return [...projectSkills, ...userSkills];
|
|
@@ -23745,9 +23973,9 @@ async function loadSkillWithReferences(skill, includeRefs) {
|
|
|
23745
23973
|
const referencesLoaded = [];
|
|
23746
23974
|
if (includeRefs && skill.references.length > 0) {
|
|
23747
23975
|
for (const ref of skill.references) {
|
|
23748
|
-
const refPath =
|
|
23976
|
+
const refPath = join35(skill.path, "references", ref);
|
|
23749
23977
|
try {
|
|
23750
|
-
let content =
|
|
23978
|
+
let content = readFileSync19(refPath, "utf-8");
|
|
23751
23979
|
content = await resolveCommandsInText(content);
|
|
23752
23980
|
referencesLoaded.push({ path: ref, content });
|
|
23753
23981
|
} catch {}
|
|
@@ -23939,10 +24167,9 @@ function formatTaskStatus(task) {
|
|
|
23939
24167
|
const duration3 = formatDuration(task.startedAt, task.completedAt);
|
|
23940
24168
|
const promptPreview = truncateText(task.prompt, 500);
|
|
23941
24169
|
let progressSection = "";
|
|
23942
|
-
if (task.progress) {
|
|
24170
|
+
if (task.progress?.lastTool) {
|
|
23943
24171
|
progressSection = `
|
|
23944
|
-
|
|
23945
|
-
Last tool: ${task.progress.lastTool ?? "N/A"}`;
|
|
24172
|
+
| Last tool | ${task.progress.lastTool} |`;
|
|
23946
24173
|
}
|
|
23947
24174
|
let lastMessageSection = "";
|
|
23948
24175
|
if (task.progress?.lastMessage) {
|
|
@@ -23955,6 +24182,16 @@ Last tool: ${task.progress.lastTool ?? "N/A"}`;
|
|
|
23955
24182
|
\`\`\`
|
|
23956
24183
|
${truncated}
|
|
23957
24184
|
\`\`\``;
|
|
24185
|
+
}
|
|
24186
|
+
let statusNote = "";
|
|
24187
|
+
if (task.status === "running") {
|
|
24188
|
+
statusNote = `
|
|
24189
|
+
|
|
24190
|
+
> **Note**: No need to wait explicitly - the system will notify you when this task completes.`;
|
|
24191
|
+
} else if (task.status === "error") {
|
|
24192
|
+
statusNote = `
|
|
24193
|
+
|
|
24194
|
+
> **Failed**: The task encountered an error. Check the last message for details.`;
|
|
23958
24195
|
}
|
|
23959
24196
|
return `# Task Status
|
|
23960
24197
|
|
|
@@ -23966,7 +24203,7 @@ ${truncated}
|
|
|
23966
24203
|
| Status | **${task.status}** |
|
|
23967
24204
|
| Duration | ${duration3} |
|
|
23968
24205
|
| Session ID | \`${task.sessionID}\` |${progressSection}
|
|
23969
|
-
|
|
24206
|
+
${statusNote}
|
|
23970
24207
|
## Original Prompt
|
|
23971
24208
|
|
|
23972
24209
|
\`\`\`
|
|
@@ -24712,7 +24949,16 @@ var AgentPermissionSchema = exports_external.object({
|
|
|
24712
24949
|
doom_loop: PermissionValue.optional(),
|
|
24713
24950
|
external_directory: PermissionValue.optional()
|
|
24714
24951
|
});
|
|
24715
|
-
var
|
|
24952
|
+
var BuiltinAgentNameSchema = exports_external.enum([
|
|
24953
|
+
"oracle",
|
|
24954
|
+
"librarian",
|
|
24955
|
+
"explore",
|
|
24956
|
+
"frontend-ui-ux-engineer",
|
|
24957
|
+
"document-writer",
|
|
24958
|
+
"multimodal-looker"
|
|
24959
|
+
]);
|
|
24960
|
+
var OverridableAgentNameSchema = exports_external.enum([
|
|
24961
|
+
"build",
|
|
24716
24962
|
"oracle",
|
|
24717
24963
|
"librarian",
|
|
24718
24964
|
"explore",
|
|
@@ -24735,7 +24981,8 @@ var HookNameSchema = exports_external.enum([
|
|
|
24735
24981
|
"rules-injector",
|
|
24736
24982
|
"background-notification",
|
|
24737
24983
|
"auto-update-checker",
|
|
24738
|
-
"ultrawork-mode"
|
|
24984
|
+
"ultrawork-mode",
|
|
24985
|
+
"agent-usage-reminder"
|
|
24739
24986
|
]);
|
|
24740
24987
|
var AgentOverrideConfigSchema = exports_external.object({
|
|
24741
24988
|
model: exports_external.string().optional(),
|
|
@@ -24750,6 +24997,7 @@ var AgentOverrideConfigSchema = exports_external.object({
|
|
|
24750
24997
|
permission: AgentPermissionSchema.optional()
|
|
24751
24998
|
});
|
|
24752
24999
|
var AgentOverridesSchema = exports_external.object({
|
|
25000
|
+
build: AgentOverrideConfigSchema.optional(),
|
|
24753
25001
|
oracle: AgentOverrideConfigSchema.optional(),
|
|
24754
25002
|
librarian: AgentOverrideConfigSchema.optional(),
|
|
24755
25003
|
explore: AgentOverrideConfigSchema.optional(),
|
|
@@ -24767,7 +25015,7 @@ var ClaudeCodeConfigSchema = exports_external.object({
|
|
|
24767
25015
|
var OhMyOpenCodeConfigSchema = exports_external.object({
|
|
24768
25016
|
$schema: exports_external.string().optional(),
|
|
24769
25017
|
disabled_mcps: exports_external.array(McpNameSchema).optional(),
|
|
24770
|
-
disabled_agents: exports_external.array(
|
|
25018
|
+
disabled_agents: exports_external.array(BuiltinAgentNameSchema).optional(),
|
|
24771
25019
|
disabled_hooks: exports_external.array(HookNameSchema).optional(),
|
|
24772
25020
|
agents: AgentOverridesSchema.optional(),
|
|
24773
25021
|
claude_code: ClaudeCodeConfigSchema.optional(),
|
|
@@ -24869,6 +25117,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
24869
25117
|
const rulesInjector = isHookEnabled("rules-injector") ? createRulesInjectorHook(ctx) : null;
|
|
24870
25118
|
const autoUpdateChecker = isHookEnabled("auto-update-checker") ? createAutoUpdateCheckerHook(ctx) : null;
|
|
24871
25119
|
const ultraworkMode = isHookEnabled("ultrawork-mode") ? createUltraworkModeHook() : null;
|
|
25120
|
+
const agentUsageReminder = isHookEnabled("agent-usage-reminder") ? createAgentUsageReminderHook(ctx) : null;
|
|
24872
25121
|
updateTerminalTitle({ sessionId: "main" });
|
|
24873
25122
|
const backgroundManager = new BackgroundManager(ctx);
|
|
24874
25123
|
const backgroundNotificationHook = isHookEnabled("background-notification") ? createBackgroundNotificationHook(backgroundManager) : null;
|
|
@@ -24898,6 +25147,14 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
24898
25147
|
...projectAgents,
|
|
24899
25148
|
...config3.agent
|
|
24900
25149
|
};
|
|
25150
|
+
if (config3.agent.build) {
|
|
25151
|
+
const existingPrompt = config3.agent.build.prompt || "";
|
|
25152
|
+
const userOverride = pluginConfig.agents?.build?.prompt || "";
|
|
25153
|
+
config3.agent.build = {
|
|
25154
|
+
...config3.agent.build,
|
|
25155
|
+
prompt: existingPrompt + BUILD_AGENT_PROMPT_EXTENSION + userOverride
|
|
25156
|
+
};
|
|
25157
|
+
}
|
|
24901
25158
|
config3.tools = {
|
|
24902
25159
|
...config3.tools
|
|
24903
25160
|
};
|
|
@@ -24957,6 +25214,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
24957
25214
|
await thinkMode?.event(input);
|
|
24958
25215
|
await anthropicAutoCompact?.event(input);
|
|
24959
25216
|
await ultraworkMode?.event(input);
|
|
25217
|
+
await agentUsageReminder?.event(input);
|
|
24960
25218
|
const { event } = input;
|
|
24961
25219
|
const props = event.properties;
|
|
24962
25220
|
if (event.type === "session.created") {
|
|
@@ -25057,6 +25315,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
25057
25315
|
await directoryReadmeInjector?.["tool.execute.after"](input, output);
|
|
25058
25316
|
await rulesInjector?.["tool.execute.after"](input, output);
|
|
25059
25317
|
await emptyTaskResponseDetector?.["tool.execute.after"](input, output);
|
|
25318
|
+
await agentUsageReminder?.["tool.execute.after"](input, output);
|
|
25060
25319
|
if (input.sessionID === getMainSessionID()) {
|
|
25061
25320
|
updateTerminalTitle({
|
|
25062
25321
|
sessionId: input.sessionID,
|