opencode-conductor-plugin 1.15.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5,6 +5,14 @@ import { readFile } from "fs/promises";
5
5
  import { fileURLToPath } from "url";
6
6
  const __filename = fileURLToPath(import.meta.url);
7
7
  const __dirname = dirname(__filename);
8
+ const safeRead = async (path) => {
9
+ try {
10
+ if (existsSync(path))
11
+ return await readFile(path, "utf-8");
12
+ }
13
+ catch (e) { }
14
+ return null;
15
+ };
8
16
  const ConductorPlugin = async (ctx) => {
9
17
  try {
10
18
  console.log("[Conductor] Initializing plugin...");
@@ -35,7 +43,7 @@ const ConductorPlugin = async (ctx) => {
35
43
  throw new Error(`Could not parse prompt text from ${filename}`);
36
44
  const defaults = {
37
45
  isOMOActive: isOMOActive ? "true" : "false",
38
- templatesDir: join(dirname(__dirname), "templates")
46
+ templatesDir: join(dirname(__dirname), "templates"),
39
47
  };
40
48
  const finalReplacements = { ...defaults, ...replacements };
41
49
  for (const [key, value] of Object.entries(finalReplacements)) {
@@ -45,7 +53,10 @@ const ConductorPlugin = async (ctx) => {
45
53
  }
46
54
  catch (error) {
47
55
  console.error(`[Conductor] Error loading prompt ${filename}:`, error);
48
- return { prompt: `SYSTEM ERROR: Failed to load prompt ${filename}`, description: "Error loading command" };
56
+ return {
57
+ prompt: `SYSTEM ERROR: Failed to load prompt ${filename}`,
58
+ description: "Error loading command",
59
+ };
49
60
  }
50
61
  };
51
62
  // 3. Load Strategies
@@ -59,12 +70,16 @@ const ConductorPlugin = async (ctx) => {
59
70
  strategySection = "SYSTEM ERROR: Could not load execution strategy.";
60
71
  }
61
72
  // 4. Load all Command Prompts (Parallel)
62
- const [setup, newTrack, implement, status, revert] = await Promise.all([
73
+ const [setup, newTrack, implement, status, revert, workflowMd] = await Promise.all([
63
74
  loadPrompt("setup.toml"),
64
75
  loadPrompt("newTrack.toml", { args: "$ARGUMENTS" }),
65
- loadPrompt("implement.toml", { track_name: "$ARGUMENTS", strategy_section: strategySection }),
76
+ loadPrompt("implement.toml", {
77
+ track_name: "$ARGUMENTS",
78
+ strategy_section: strategySection,
79
+ }),
66
80
  loadPrompt("status.toml"),
67
- loadPrompt("revert.toml", { target: "$ARGUMENTS" })
81
+ loadPrompt("revert.toml", { target: "$ARGUMENTS" }),
82
+ safeRead(join(ctx.directory, "conductor", "workflow.md")),
68
83
  ]);
69
84
  // 5. Extract Agent Prompt
70
85
  const agentMd = await readFile(join(__dirname, "prompts", "agent", "conductor.md"), "utf-8");
@@ -75,57 +90,84 @@ const ConductorPlugin = async (ctx) => {
75
90
  console.log("[Conductor] config handler: Merging commands and agent...");
76
91
  config.command = {
77
92
  ...(config.command || {}),
78
- "conductor:setup": { template: setup.prompt, description: setup.description, agent: "conductor" },
79
- "conductor:newTrack": { template: newTrack.prompt, description: newTrack.description, agent: "conductor" },
80
- "conductor:implement": { template: implement.prompt, description: implement.description },
81
- "conductor:status": { template: status.prompt, description: status.description, agent: "conductor" },
82
- "conductor:revert": { template: revert.prompt, description: revert.description, agent: "conductor" }
93
+ "conductor:setup": {
94
+ template: setup.prompt,
95
+ description: setup.description,
96
+ agent: "conductor",
97
+ },
98
+ "conductor:newTrack": {
99
+ template: newTrack.prompt,
100
+ description: newTrack.description,
101
+ agent: "conductor",
102
+ },
103
+ "conductor:implement": {
104
+ template: implement.prompt,
105
+ description: implement.description,
106
+ },
107
+ "conductor:status": {
108
+ template: status.prompt,
109
+ description: status.description,
110
+ agent: "conductor",
111
+ },
112
+ "conductor:revert": {
113
+ template: revert.prompt,
114
+ description: revert.description,
115
+ agent: "conductor",
116
+ },
83
117
  };
84
118
  config.agent = {
85
119
  ...(config.agent || {}),
86
- "conductor": {
120
+ conductor: {
87
121
  description: "Spec-Driven Development Architect.",
88
122
  mode: "primary",
89
- prompt: agentPrompt,
123
+ prompt: agentPrompt + workflowMd,
90
124
  permission: {
91
125
  edit: "allow",
92
126
  bash: "allow",
93
127
  webfetch: "allow",
94
128
  doom_loop: "allow",
95
- external_directory: "deny"
96
- }
97
- }
129
+ external_directory: "deny",
130
+ },
131
+ },
98
132
  };
99
133
  },
100
134
  "tool.execute.before": async (input, output) => {
101
- if (input.tool === "delegate_to_agent") {
102
- const agentName = (output.args.agent_name || output.args.agent || "");
103
- // Sisyphus must be capital S
104
- if (agentName.includes("Sisyphus")) {
105
- const conductorDir = join(ctx.directory, "conductor");
106
- const safeRead = async (path) => {
107
- try {
108
- if (existsSync(path))
109
- return await readFile(path, "utf-8");
110
- }
111
- catch (e) { }
112
- return null;
113
- };
114
- const workflowMd = await safeRead(join(conductorDir, "workflow.md"));
135
+ const delegationTools = [
136
+ "delegate_to_agent",
137
+ "task",
138
+ "background_task",
139
+ "call_omo_agent",
140
+ ];
141
+ if (delegationTools.includes(input.tool)) {
142
+ const conductorDir = join(ctx.directory, "conductor");
143
+ const workflowMd = await safeRead(join(conductorDir, "workflow.md"));
144
+ if (workflowMd) {
115
145
  let injection = "\n\n--- [SYSTEM INJECTION: CONDUCTOR CONTEXT PACKET] ---\n";
116
- injection += "You are receiving this task from the Conductor Architect.\n";
117
- if (workflowMd) {
118
- injection += "\n### DEVELOPMENT WORKFLOW\n" + workflowMd + "\n";
119
- }
146
+ injection +=
147
+ "You are receiving this task from the Conductor Architect.\n";
148
+ injection +=
149
+ "You MUST adhere to the following project workflow rules:\n";
150
+ injection += "\n### DEVELOPMENT WORKFLOW\n" + workflowMd + "\n";
120
151
  if (implement?.prompt) {
121
- injection += "\n### IMPLEMENTATION PROTOCOL\n" + implement.prompt + "\n";
152
+ injection +=
153
+ "\n### IMPLEMENTATION PROTOCOL\n" + implement.prompt + "\n";
122
154
  }
123
- injection += "\n### DELEGATED AUTHORITY\n- **EXECUTE:** Implement the requested task.\n- **REFINE:** You have authority to update `plan.md`.\n";
155
+ injection +=
156
+ "\n### DELEGATED AUTHORITY\n- **EXECUTE:** Implement the requested task.\n- **REFINE:** You have authority to update `plan.md`.\n";
124
157
  injection += "--- [END INJECTION] ---\n";
125
- output.args.objective += injection;
158
+ // Inject into the primary instruction field depending on the tool's schema
159
+ if (typeof output.args.objective === "string") {
160
+ output.args.objective += injection;
161
+ }
162
+ else if (typeof output.args.prompt === "string") {
163
+ output.args.prompt += injection;
164
+ }
165
+ else if (typeof output.args.instruction === "string") {
166
+ output.args.instruction += injection;
167
+ }
126
168
  }
127
169
  }
128
- }
170
+ },
129
171
  };
130
172
  }
131
173
  catch (err) {
@@ -27,7 +27,7 @@ Your mission is to ensure that software development follows a rigorous, context-
27
27
  - **Model Selection**: You prefer "flash" models for efficiency and speed during planning and tool orchestration.
28
28
  - **Protocol First**: Never start implementing code until a Track has an approved Spec and Plan.
29
29
  - **Collaboration**: You work alongside the user. When in doubt about an architectural choice or product goal, always ask for clarification.
30
- - **Synergy with Sisyphus**: If the user is using `oh-my-opencode`, you act as the Technical Lead/Architect. You can delegate UI work to `@frontend-ui-ux-engineer` or documentation to `@document-writer` if their roles are available.
30
+ - **Synergy with Sisyphus**: If the user is using `oh-my-opencode`, you act as the Technical Lead/Architect. You can delegate UI work to `@frontend-ui-ux-engineer` or documentation to `@document-writer` if their roles are available. There are plenty of agents to choose from to help in different regards
31
31
 
32
32
  ## Loop Protection Directive (CRITICAL)
33
33
  If you see a "[SYSTEM REMINDER - TODO CONTINUATION]" or "Continue" prompt from an enforcer while you are waiting for user input, you MUST ignore it. Respond with: "I am currently in an interactive Conductor phase. Awaiting user response."
@@ -17,7 +17,7 @@ Your mission is to ensure that software development follows a rigorous, context-
17
17
  - **Model Selection**: You prefer "flash" models for efficiency and speed during planning and tool orchestration.
18
18
  - **Protocol First**: Never start implementing code until a Track has an approved Spec and Plan.
19
19
  - **Collaboration**: You work alongside the user. When in doubt about an architectural choice or product goal, always ask for clarification.
20
- - **Synergy with Sisyphus**: If the user is using `oh-my-opencode`, you act as the Technical Lead/Architect. You can delegate UI work to `@frontend-ui-ux-engineer` or documentation to `@document-writer` if their roles are available.
20
+ - **Synergy with Sisyphus**: If the user is using `oh-my-opencode`, you act as the Technical Lead/Architect. You can delegate UI work to `@frontend-ui-ux-engineer` or documentation to `@document-writer` if their roles are available. There are plenty of agents to choose from to help in different regards
21
21
 
22
22
  ## Loop Protection Directive (CRITICAL)
23
23
  If you see a "[SYSTEM REMINDER - TODO CONTINUATION]" or "Continue" prompt from an enforcer while you are waiting for user input, you MUST ignore it. Respond with: "I am currently in an interactive Conductor phase. Awaiting user response."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-conductor-plugin",
3
- "version": "1.15.0",
3
+ "version": "1.16.0",
4
4
  "description": "Conductor plugin for OpenCode",
5
5
  "type": "module",
6
6
  "repository": "derekbar90/opencode-conductor",