opencode-conductor-plugin 1.23.0 → 1.24.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.
@@ -1,7 +1,11 @@
1
- import { type PluginInput } from "@opencode-ai/plugin";
2
1
  import { type ToolDefinition } from "@opencode-ai/plugin/tool";
3
- export declare function createSetupTool(ctx: PluginInput): ToolDefinition;
4
- export declare function createNewTrackTool(ctx: PluginInput): ToolDefinition;
5
- export declare function createImplementTool(ctx: PluginInput): ToolDefinition;
6
- export declare function createStatusTool(ctx: PluginInput): ToolDefinition;
7
- export declare function createRevertTool(ctx: PluginInput): ToolDefinition;
2
+ export declare const setupCommand: (ctx: import("@opencode-ai/plugin").PluginInput) => ToolDefinition;
3
+ export declare const newTrackCommand: (ctx: import("@opencode-ai/plugin").PluginInput) => ToolDefinition;
4
+ export declare const implementCommand: (ctx: import("@opencode-ai/plugin").PluginInput) => ToolDefinition;
5
+ export declare const statusCommand: (ctx: import("@opencode-ai/plugin").PluginInput) => ToolDefinition;
6
+ export declare const revertCommand: (ctx: import("@opencode-ai/plugin").PluginInput) => ToolDefinition;
7
+ export declare function createSetupTool(ctx: any): ToolDefinition;
8
+ export declare function createNewTrackTool(ctx: any): ToolDefinition;
9
+ export declare function createImplementTool(ctx: any): ToolDefinition;
10
+ export declare function createStatusTool(ctx: any): ToolDefinition;
11
+ export declare function createRevertTool(ctx: any): ToolDefinition;
@@ -1,99 +1,81 @@
1
1
  import { tool } from "@opencode-ai/plugin/tool";
2
+ import { createConductorCommand } from "../utils/commandFactory.js";
2
3
  import { join, dirname } from "path";
3
- import { readFile } from "fs/promises";
4
4
  import { fileURLToPath } from "url";
5
+ import { readFile } from "fs/promises";
5
6
  const __filename = fileURLToPath(import.meta.url);
6
7
  const __dirname = dirname(__filename);
7
- // Helper to load and process prompt templates
8
- async function loadPrompt(filename, replacements = {}) {
9
- const promptPath = join(__dirname, "..", "prompts", filename);
10
- try {
11
- const content = await readFile(promptPath, "utf-8");
12
- const descMatch = content.match(/description\s*=\s*"([^"]+)"/);
13
- const description = descMatch ? descMatch[1] : "Conductor Command";
14
- const promptMatch = content.match(/prompt\s*=\s*"""([\s\S]*?)"""/);
15
- let promptText = promptMatch ? promptMatch[1] : "";
16
- if (!promptText)
17
- throw new Error(`Could not parse prompt text from ${filename}`);
18
- const defaults = {
19
- templatesDir: join(dirname(dirname(__dirname)), "templates"),
8
+ export const setupCommand = createConductorCommand({
9
+ name: "setup.toml",
10
+ description: "Scaffolds the project and sets up the Conductor environment",
11
+ args: {},
12
+ });
13
+ export const newTrackCommand = createConductorCommand({
14
+ name: "newTrack.toml",
15
+ description: "Plans a track, generates track-specific spec documents and updates the tracks file",
16
+ args: {
17
+ description: tool.schema.string().optional().describe("Brief description of the track (feature, bug fix, chore, etc.)"),
18
+ },
19
+ additionalContext: async (ctx, args) => {
20
+ return {
21
+ args: args.description || "",
20
22
  };
21
- const finalReplacements = { ...defaults, ...replacements };
22
- for (const [key, value] of Object.entries(finalReplacements)) {
23
- promptText = promptText.replaceAll(`{{${key}}}`, value || "");
23
+ },
24
+ });
25
+ export const implementCommand = createConductorCommand({
26
+ name: "implement.toml",
27
+ description: "Executes the tasks defined in the specified track's plan",
28
+ args: {
29
+ track_name: tool.schema.string().optional().describe("Name or description of the track to implement"),
30
+ },
31
+ additionalContext: async (ctx, args) => {
32
+ // 1. Choose strategy based on OMO activity
33
+ const strategyFile = ctx.isOMOActive ? "delegate.md" : "manual.md";
34
+ const strategyPath = join(__dirname, "../prompts/strategies", strategyFile);
35
+ let strategySection = "";
36
+ try {
37
+ strategySection = await readFile(strategyPath, "utf-8");
38
+ }
39
+ catch (e) {
40
+ console.warn(`[Conductor] Failed to load strategy ${strategyFile}:`, e);
41
+ strategySection = "Error: Could not load execution strategy.";
24
42
  }
25
- return { prompt: promptText, description: description };
26
- }
27
- catch (error) {
28
- console.error(`[Conductor] Error loading prompt ${filename}:`, error);
29
43
  return {
30
- prompt: `SYSTEM ERROR: Failed to load prompt ${filename}`,
31
- description: "Error loading command",
44
+ strategy_section: strategySection,
45
+ track_name: args.track_name || "",
32
46
  };
33
- }
34
- }
47
+ },
48
+ });
49
+ export const statusCommand = createConductorCommand({
50
+ name: "status.toml",
51
+ description: "Displays the current progress of the project",
52
+ args: {},
53
+ });
54
+ export const revertCommand = createConductorCommand({
55
+ name: "revert.toml",
56
+ description: "Reverts previous work",
57
+ args: {
58
+ target: tool.schema.string().optional().describe("Target to revert (e.g., 'track <track_id>', 'phase <phase_name>', 'task <task_name>')"),
59
+ },
60
+ additionalContext: async (ctx, args) => {
61
+ return {
62
+ target: args.target || "",
63
+ };
64
+ },
65
+ });
66
+ // Export as functions for backward compatibility
35
67
  export function createSetupTool(ctx) {
36
- return tool({
37
- description: "Scaffolds the project and sets up the Conductor environment",
38
- args: {},
39
- async execute(args) {
40
- const { prompt } = await loadPrompt("setup.toml");
41
- return prompt;
42
- },
43
- });
68
+ return setupCommand(ctx);
44
69
  }
45
70
  export function createNewTrackTool(ctx) {
46
- return tool({
47
- description: "Plans a track, generates track-specific spec documents and updates the tracks file",
48
- args: {
49
- description: tool.schema.string().optional().describe("Brief description of the track (feature, bug fix, chore, etc.)"),
50
- },
51
- async execute(args) {
52
- const trackDescription = args.description || "";
53
- const { prompt } = await loadPrompt("newTrack.toml", {
54
- args: trackDescription,
55
- });
56
- return prompt;
57
- },
58
- });
71
+ return newTrackCommand(ctx);
59
72
  }
60
73
  export function createImplementTool(ctx) {
61
- return tool({
62
- description: "Executes the tasks defined in the specified track's plan",
63
- args: {
64
- track_name: tool.schema.string().optional().describe("Name or description of the track to implement"),
65
- },
66
- async execute(args) {
67
- const trackName = args.track_name || "";
68
- const { prompt } = await loadPrompt("implement.toml", {
69
- track_name: trackName,
70
- });
71
- return prompt;
72
- },
73
- });
74
+ return implementCommand(ctx);
74
75
  }
75
76
  export function createStatusTool(ctx) {
76
- return tool({
77
- description: "Displays the current progress of the project",
78
- args: {},
79
- async execute(args) {
80
- const { prompt } = await loadPrompt("status.toml");
81
- return prompt;
82
- },
83
- });
77
+ return statusCommand(ctx);
84
78
  }
85
79
  export function createRevertTool(ctx) {
86
- return tool({
87
- description: "Reverts previous work",
88
- args: {
89
- target: tool.schema.string().optional().describe("Target to revert (e.g., 'track <track_id>', 'phase <phase_name>', 'task <task_name>')"),
90
- },
91
- async execute(args) {
92
- const target = args.target || "";
93
- const { prompt } = await loadPrompt("revert.toml", {
94
- target: target,
95
- });
96
- return prompt;
97
- },
98
- });
80
+ return revertCommand(ctx);
99
81
  }
@@ -0,0 +1,10 @@
1
+ import { type PluginInput } from "@opencode-ai/plugin";
2
+ import { type ToolDefinition } from "@opencode-ai/plugin/tool";
3
+ interface ConductorCommandConfig {
4
+ name: string;
5
+ description: string;
6
+ args: Record<string, any>;
7
+ additionalContext?: (ctx: PluginInput, args: any) => Promise<Record<string, string>>;
8
+ }
9
+ export declare function createConductorCommand(config: ConductorCommandConfig): (ctx: PluginInput) => ToolDefinition;
10
+ export {};
@@ -0,0 +1,53 @@
1
+ import { tool } from "@opencode-ai/plugin/tool";
2
+ import { join, dirname } from "path";
3
+ import { readFile } from "fs/promises";
4
+ import { fileURLToPath } from "url";
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+ // Helper to load and process prompt templates
8
+ async function loadPrompt(filename, replacements = {}) {
9
+ const promptPath = join(__dirname, "..", "prompts", filename);
10
+ try {
11
+ const content = await readFile(promptPath, "utf-8");
12
+ const descMatch = content.match(/description\s*=\s*"([^"]+)"/);
13
+ const description = descMatch ? descMatch[1] : "Conductor Command";
14
+ const promptMatch = content.match(/prompt\s*=\s*"""([\s\S]*?)"""/);
15
+ let promptText = promptMatch ? promptMatch[1] : "";
16
+ if (!promptText)
17
+ throw new Error(`Could not parse prompt text from ${filename}`);
18
+ const defaults = {
19
+ templatesDir: join(dirname(dirname(__dirname)), "templates"),
20
+ };
21
+ const finalReplacements = { ...defaults, ...replacements };
22
+ for (const [key, value] of Object.entries(finalReplacements)) {
23
+ promptText = promptText.replaceAll(`{{${key}}}`, value || "");
24
+ }
25
+ return { prompt: promptText, description: description };
26
+ }
27
+ catch (error) {
28
+ console.error(`[Conductor] Error loading prompt ${filename}:`, error);
29
+ return {
30
+ prompt: `SYSTEM ERROR: Failed to load prompt ${filename}`,
31
+ description: "Error loading command",
32
+ };
33
+ }
34
+ }
35
+ export function createConductorCommand(config) {
36
+ return (ctx) => {
37
+ return tool({
38
+ description: config.description,
39
+ args: config.args,
40
+ async execute(args) {
41
+ // Get additional context if provided (this can override/extend args)
42
+ const additionalContext = config.additionalContext
43
+ ? await config.additionalContext(ctx, args)
44
+ : {};
45
+ // Merge additionalContext into replacements
46
+ // additionalContext takes precedence and can provide custom mappings
47
+ const replacements = { ...additionalContext };
48
+ const { prompt } = await loadPrompt(config.name, replacements);
49
+ return prompt;
50
+ },
51
+ });
52
+ };
53
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-conductor-plugin",
3
- "version": "1.23.0",
3
+ "version": "1.24.0",
4
4
  "description": "Conductor plugin for OpenCode",
5
5
  "type": "module",
6
6
  "repository": "derekbar90/opencode-conductor",