opencode-conductor-plugin 1.8.2 → 1.9.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/README.md +13 -11
- package/dist/commands/implement.d.ts +1 -2
- package/dist/commands/implement.js +24 -12
- package/dist/commands/newTrack.d.ts +1 -2
- package/dist/commands/newTrack.js +6 -15
- package/dist/commands/revert.d.ts +1 -2
- package/dist/commands/revert.js +4 -12
- package/dist/commands/setup.d.ts +1 -2
- package/dist/commands/setup.js +4 -16
- package/dist/commands/status.d.ts +1 -2
- package/dist/commands/status.js +4 -13
- package/dist/prompts/agent/conductor.md +7 -7
- package/dist/prompts/commands/{c-implement.md → conductor:implement.md} +0 -1
- package/dist/prompts/commands/{c-new.md → conductor:newTrack.md} +0 -1
- package/dist/prompts/commands/conductor:revert.md +4 -0
- package/dist/prompts/commands/{c-setup.md → conductor:setup.md} +0 -1
- package/dist/prompts/commands/{c-status.md → conductor:status.md} +0 -1
- package/dist/prompts/implement.toml +6 -18
- package/dist/prompts/strategies/delegate.md +11 -0
- package/dist/prompts/strategies/manual.md +9 -0
- package/dist/utils/commandFactory.d.ts +10 -0
- package/dist/utils/commandFactory.js +47 -0
- package/package.json +2 -2
- package/dist/prompts/commands/c-revert.md +0 -5
- package/dist/utils/promptLoader.d.ts +0 -1
- package/dist/utils/promptLoader.js +0 -23
package/README.md
CHANGED
|
@@ -11,12 +11,14 @@ The philosophy is simple: **control your code by controlling your context.** By
|
|
|
11
11
|
## 🚀 Key Features
|
|
12
12
|
|
|
13
13
|
* **Specialized `@conductor` Agent**: A dedicated subagent that acts as your Project Architect and Technical Lead.
|
|
14
|
-
* **Native Slash Commands**: Integrated shortcuts like `/
|
|
14
|
+
* **Native Slash Commands**: Integrated shortcuts like `/conductor:setup`, `/conductor:newTrack`, and `/conductor:implement` for frictionless project management.
|
|
15
|
+
* **Modern Permissions**: Fully compatible with OpenCode v1.1.1 granular permission system.
|
|
15
16
|
* **Protocol-Driven Workflow**: Automated enforcement of the **Context -> Spec -> Plan -> Implement** lifecycle.
|
|
16
17
|
* **Smart Revert**: A Git-aware revert system that understands logical units of work (Tracks, Phases, Tasks) instead of just raw commit hashes.
|
|
17
18
|
* **19+ Style Templates**: Built-in support for a vast range of languages including Rust, Solidity, Zig, Julia, Kotlin, Swift, and more.
|
|
18
19
|
* **Zero-Config Bootstrap**: Automatically installs agents and commands to your global OpenCode configuration on first run.
|
|
19
20
|
* **Sisyphus Synergy**: Optimized to work alongside [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode) for a multi-agent team experience.
|
|
21
|
+
* **Agent Agnostic**: Commands can be invoked by any agent, giving you the freedom to choose your primary interface.
|
|
20
22
|
|
|
21
23
|
---
|
|
22
24
|
|
|
@@ -24,18 +26,18 @@ The philosophy is simple: **control your code by controlling your context.** By
|
|
|
24
26
|
|
|
25
27
|
Conductor organizes your work into **Tracks** (features or bug fixes). Every Track follows three mandatory phases:
|
|
26
28
|
|
|
27
|
-
### 1. Project Initialization (`/
|
|
28
|
-
Run this once per project. The
|
|
29
|
+
### 1. Project Initialization (`/conductor:setup`)
|
|
30
|
+
Run this once per project. The agent will interview you to define:
|
|
29
31
|
* **Product Vision**: Target users, core goals, and primary features.
|
|
30
32
|
* **Tech Stack**: Languages, frameworks, and databases.
|
|
31
33
|
* **Workflow Rules**: Testing standards (e.g., TDD), commit strategies, and documentation patterns.
|
|
32
34
|
|
|
33
|
-
### 2. Track Planning (`/
|
|
34
|
-
When you're ready for a new task, tell
|
|
35
|
+
### 2. Track Planning (`/conductor:newTrack`)
|
|
36
|
+
When you're ready for a new task, tell the agent what you want to build.
|
|
35
37
|
* **Specification (`spec.md`)**: Conductor asks 3-5 targeted questions to clarify the "What" and "Why".
|
|
36
38
|
* **Implementation Plan (`plan.md`)**: Once the spec is approved, Conductor generates a step-by-step checklist adhering to your project's workflow rules.
|
|
37
39
|
|
|
38
|
-
### 3. Autonomous Implementation (`/
|
|
40
|
+
### 3. Autonomous Implementation (`/conductor:implement`)
|
|
39
41
|
The agent works through the `plan.md` checklist, executing tasks, running tests, and making semantic commits automatically until the Track is complete.
|
|
40
42
|
|
|
41
43
|
---
|
|
@@ -92,11 +94,11 @@ We highly recommend pinning the `@conductor` agent to a "flash" model for optima
|
|
|
92
94
|
|
|
93
95
|
| Command | Description |
|
|
94
96
|
| :--- | :--- |
|
|
95
|
-
| `/
|
|
96
|
-
| `/
|
|
97
|
-
| `/
|
|
98
|
-
| `/
|
|
99
|
-
| `/
|
|
97
|
+
| `/conductor:setup` | Initialize the `conductor/` directory and project "Constitution". |
|
|
98
|
+
| `/conductor:newTrack "desc"` | Start a new feature/bug Track with spec and plan generation. |
|
|
99
|
+
| `/conductor:implement` | Start implementing the next pending task in the current track. |
|
|
100
|
+
| `/conductor:status` | Get a high-level overview of project progress and active tracks. |
|
|
101
|
+
| `/conductor:revert` | Interactively select a task, phase, or track to undo via Git. |
|
|
100
102
|
|
|
101
103
|
---
|
|
102
104
|
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const implementCommand: (ctx: any) => ToolDefinition;
|
|
1
|
+
export declare const implementCommand: (ctx: any) => import("@opencode-ai/plugin/tool").ToolDefinition;
|
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
-
import {
|
|
3
|
-
import { join } from "path";
|
|
4
|
-
import {
|
|
5
|
-
|
|
2
|
+
import { createConductorCommand } from "../utils/commandFactory.js";
|
|
3
|
+
import { join, dirname } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import { readFile } from "fs/promises";
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
export const implementCommand = createConductorCommand({
|
|
9
|
+
name: "implement.toml",
|
|
6
10
|
description: "Implements tasks from a Conductor track.",
|
|
7
11
|
args: {
|
|
8
12
|
track_name: tool.schema.string().optional().describe("Specific track to implement. If omitted, selects the next incomplete track."),
|
|
9
13
|
},
|
|
10
|
-
async
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
additionalContext: async (ctx, args) => {
|
|
15
|
+
// 1. Choose strategy based on OMO activity
|
|
16
|
+
const strategyFile = ctx.isOMOActive ? "delegate.md" : "manual.md";
|
|
17
|
+
const strategyPath = join(__dirname, "../prompts/strategies", strategyFile);
|
|
18
|
+
let strategySection = "";
|
|
19
|
+
try {
|
|
20
|
+
strategySection = await readFile(strategyPath, "utf-8");
|
|
14
21
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
catch (e) {
|
|
23
|
+
console.warn(`[Conductor] Failed to load strategy ${strategyFile}:`, e);
|
|
24
|
+
strategySection = "Error: Could not load execution strategy.";
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
strategy_section: strategySection,
|
|
28
|
+
track_name: args.track_name || ""
|
|
29
|
+
};
|
|
30
|
+
}
|
|
19
31
|
});
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const newTrackCommand: (ctx: any) => ToolDefinition;
|
|
1
|
+
export declare const newTrackCommand: (ctx: any) => import("@opencode-ai/plugin/tool").ToolDefinition;
|
|
@@ -1,21 +1,12 @@
|
|
|
1
1
|
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export const newTrackCommand = (ctx) => tool({
|
|
2
|
+
import { createConductorCommand } from "../utils/commandFactory.js";
|
|
3
|
+
export const newTrackCommand = createConductorCommand({
|
|
4
|
+
name: "newTrack.toml",
|
|
6
5
|
description: "Creates a new track (feature/bug) in the Conductor system. IMPORTANT: Do NOT create any todos using 'todowrite' or 'task' tools before or during this command, as it manages its own interactive state and will conflict with continuation enforcers.",
|
|
7
6
|
args: {
|
|
8
7
|
description: tool.schema.string().optional().describe("Brief description of the track."),
|
|
9
8
|
},
|
|
10
|
-
async
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return "Conductor is not set up. Please run `conductor_setup`.";
|
|
14
|
-
}
|
|
15
|
-
// Map the description to {{args}} in the legacy TOML
|
|
16
|
-
return await loadPrompt("newTrack.toml", {
|
|
17
|
-
args: args.description || "",
|
|
18
|
-
isOMOActive: ctx.isOMOActive ? "true" : "false"
|
|
19
|
-
});
|
|
20
|
-
},
|
|
9
|
+
additionalContext: async (_, args) => ({
|
|
10
|
+
args: args.description || ""
|
|
11
|
+
})
|
|
21
12
|
});
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const revertCommand: (ctx: any) => ToolDefinition;
|
|
1
|
+
export declare const revertCommand: (ctx: any) => import("@opencode-ai/plugin/tool").ToolDefinition;
|
package/dist/commands/revert.js
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
|
+
import { createConductorCommand } from "../utils/commandFactory.js";
|
|
1
2
|
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { loadPrompt } from "../utils/promptLoader.js";
|
|
5
|
-
export const revertCommand = (ctx) => tool({
|
|
3
|
+
export const revertCommand = createConductorCommand({
|
|
4
|
+
name: "revert.toml",
|
|
6
5
|
description: "Reverts a Conductor track, phase, or task.",
|
|
7
6
|
args: {
|
|
8
7
|
target: tool.schema.string().optional().describe("ID or description of what to revert."),
|
|
9
|
-
}
|
|
10
|
-
async execute(args) {
|
|
11
|
-
const conductorDir = join(ctx.directory, "conductor");
|
|
12
|
-
if (!existsSync(join(conductorDir, "tracks.md"))) {
|
|
13
|
-
return "Conductor is not set up.";
|
|
14
|
-
}
|
|
15
|
-
return await loadPrompt("revert.toml");
|
|
16
|
-
},
|
|
8
|
+
}
|
|
17
9
|
});
|
package/dist/commands/setup.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const setupCommand: (ctx: any) => ToolDefinition;
|
|
1
|
+
export declare const setupCommand: (ctx: any) => import("@opencode-ai/plugin/tool").ToolDefinition;
|
package/dist/commands/setup.js
CHANGED
|
@@ -1,22 +1,10 @@
|
|
|
1
1
|
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { fileURLToPath } from "url";
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
-
const __dirname = dirname(__filename);
|
|
8
|
-
export const setupCommand = (ctx) => tool({
|
|
2
|
+
import { createConductorCommand } from "../utils/commandFactory.js";
|
|
3
|
+
export const setupCommand = createConductorCommand({
|
|
4
|
+
name: "setup.toml",
|
|
9
5
|
description: "Sets up the Conductor environment for the project. Call this to start or resume the setup process. IMPORTANT: Do NOT create any todos using 'todowrite' or 'task' tools before or during this command, as it manages its own interactive state and will conflict with continuation enforcers.",
|
|
10
6
|
args: {
|
|
11
7
|
user_input: tool.schema.string().optional().describe("The user's response to a previous question, if applicable."),
|
|
12
8
|
},
|
|
13
|
-
|
|
14
|
-
const stateManager = new StateManager(ctx.directory);
|
|
15
|
-
// Resolve the absolute path to the templates directory in the distribution
|
|
16
|
-
const templatesDir = join(__dirname, "../templates");
|
|
17
|
-
return await loadPrompt("setup.toml", {
|
|
18
|
-
templatesDir,
|
|
19
|
-
isOMOActive: ctx.isOMOActive ? "true" : "false"
|
|
20
|
-
});
|
|
21
|
-
},
|
|
9
|
+
requiresSetup: false // Setup command is what creates the setup
|
|
22
10
|
});
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const statusCommand: (ctx: any) => ToolDefinition;
|
|
1
|
+
export declare const statusCommand: (ctx: any) => import("@opencode-ai/plugin/tool").ToolDefinition;
|
package/dist/commands/status.js
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { loadPrompt } from "../utils/promptLoader.js";
|
|
5
|
-
export const statusCommand = (ctx) => tool({
|
|
1
|
+
import { createConductorCommand } from "../utils/commandFactory.js";
|
|
2
|
+
export const statusCommand = createConductorCommand({
|
|
3
|
+
name: "status.toml",
|
|
6
4
|
description: "Shows the status of Conductor tracks.",
|
|
7
|
-
args: {}
|
|
8
|
-
async execute(args) {
|
|
9
|
-
const conductorDir = join(ctx.directory, "conductor");
|
|
10
|
-
if (!existsSync(join(conductorDir, "tracks.md"))) {
|
|
11
|
-
return "Conductor is not set up.";
|
|
12
|
-
}
|
|
13
|
-
return await loadPrompt("status.toml");
|
|
14
|
-
},
|
|
5
|
+
args: {}
|
|
15
6
|
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Spec-Driven Development Architect. Manages the project lifecycle using the Conductor protocol.
|
|
3
3
|
mode: primary
|
|
4
|
-
|
|
5
|
-
conductor_setup:
|
|
6
|
-
conductor_new_track:
|
|
7
|
-
conductor_implement:
|
|
8
|
-
conductor_status:
|
|
9
|
-
conductor_revert:
|
|
4
|
+
permission:
|
|
5
|
+
conductor_setup: allow
|
|
6
|
+
conductor_new_track: allow
|
|
7
|
+
conductor_implement: allow
|
|
8
|
+
conductor_status: allow
|
|
9
|
+
conductor_revert: allow
|
|
10
10
|
---
|
|
11
11
|
# Conductor Agent
|
|
12
12
|
|
|
@@ -32,4 +32,4 @@ Your mission is to ensure that software development follows a rigorous, context-
|
|
|
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."
|
|
34
34
|
|
|
35
|
-
**Proactive OMO Protection:** If `oh-my-opencode` is active, at the start of any interactive session (setup or planning), you should create a temporary blocking task using the `task` tool: `[WAITING] Conductor interactive session in progress`. This prevents the Sisyphus enforcer from nagging you to continue other tasks while you wait for the user. Delete it once the session concludes.
|
|
35
|
+
**Proactive OMO Protection:** If `oh-my-opencode` is active, at the start of any interactive session (setup or planning), you should create a temporary blocking task using the `task` tool: `[WAITING] Conductor interactive session in progress`. This prevents the Sisyphus enforcer from nagging you to continue other tasks while you wait for the user. Delete it once the session concludes.
|
|
@@ -69,24 +69,12 @@ CRITICAL: You must validate the success of every tool call. If any tool call fai
|
|
|
69
69
|
- `conductor/workflow.md`
|
|
70
70
|
c. **Error Handling:** If you fail to read any of these files, you MUST stop and inform the user of the error.
|
|
71
71
|
|
|
72
|
-
5.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
> "I am delegating the implementation of task: '[Task Name]' to you.
|
|
79
|
-
>
|
|
80
|
-
> **Goal:** Execute this task. You have Engineering Authority to update `plan.md` if needed.
|
|
81
|
-
> **Constraint:** If you modify the plan or spec, stop and report 'PLAN_UPDATED'."
|
|
82
|
-
- *Verification:*
|
|
83
|
-
- If Sisyphus reports 'PLAN_UPDATED', you MUST **reload** `plan.md` before proceeding.
|
|
84
|
-
- If Sisyphus reports success, verify the task against the plan and move to the next.
|
|
85
|
-
c. **Manual Implementation (Standard Mode):** If `isOMOActive` is "false" or if you choose to implement directly, you MUST now loop through each task in the track's `plan.md` one by one.
|
|
86
|
-
d. **For Each Task, You MUST:**
|
|
87
|
-
i. **Defer to Workflow:** The `workflow.md` file is the **single source of truth** for the entire task lifecycle. You MUST now read and execute the procedures defined in the "Task Workflow" section of the `workflow.md` file you have in your context. Follow its steps for implementation, testing, and committing precisely.
|
|
88
|
-
|
|
89
|
-
5. **Finalize Track:**
|
|
72
|
+
5. **Execute Tasks and Update Track Plan:**
|
|
73
|
+
a. **Announce:** State that you will now execute the tasks from the track's `plan.md`.
|
|
74
|
+
b. **Execute Strategy:**
|
|
75
|
+
{{strategy_section}}
|
|
76
|
+
|
|
77
|
+
6. **Finalize Track:**
|
|
90
78
|
- After all tasks in the track's local `plan.md` are completed, you MUST update the track's status in the tracks file.
|
|
91
79
|
- This requires finding the specific heading for the track (e.g., `## [~] Track: <Description>`) and replacing it with the completed status (e.g., `## [x] Track: <Description>`).
|
|
92
80
|
- Announce that the track is fully complete and the tracks file has been updated.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
**MODE: SYNERGY (Architectural Delegation)**
|
|
2
|
+
You are acting as the **Architect**. Your responsibility is to oversee the track while delegating execution to **Sisyphus**.
|
|
3
|
+
|
|
4
|
+
**DIRECTIVE:**
|
|
5
|
+
1. **Do NOT implement code yourself.**
|
|
6
|
+
2. **Delegate:** For each task in `plan.md`, call `@sisyphus`.
|
|
7
|
+
* *Note:* The system will automatically inject the full project context for you.
|
|
8
|
+
* *Instruction:* Tell Sisyphus: "Execute this task. You have authority to update `plan.md` if needed. Report 'PLAN_UPDATED' if you do."
|
|
9
|
+
3. **Verify:**
|
|
10
|
+
* If Sisyphus reports 'PLAN_UPDATED', you MUST **reload** `plan.md` before the next task.
|
|
11
|
+
* If success, verify against the plan and proceed to the next task.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
**MODE: STANDARD (Manual Implementation)**
|
|
2
|
+
You are acting as the **Developer**. Your responsibility is to implement the code, tests, and documentation yourself.
|
|
3
|
+
|
|
4
|
+
**DIRECTIVE:**
|
|
5
|
+
1. **Implement Manually:** Loop through each task in `plan.md` one by one.
|
|
6
|
+
2. **Workflow:** Follow the `workflow.md` TDD protocol precisely (Red -> Green -> Refactor).
|
|
7
|
+
3. **Commits:**
|
|
8
|
+
* **AUTHORITY OVERRIDE:** You have explicit authority to create Git commits as defined in the workflow.
|
|
9
|
+
* Do not ask for further permission for the granular task commits defined in `workflow.md`.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ToolDefinition } from "@opencode-ai/plugin/tool";
|
|
2
|
+
interface CommandOptions {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
args?: any;
|
|
6
|
+
requiresSetup?: boolean;
|
|
7
|
+
additionalContext?: (ctx: any, args: any) => Promise<Record<string, string>>;
|
|
8
|
+
}
|
|
9
|
+
export declare const createConductorCommand: (options: CommandOptions) => (ctx: any) => ToolDefinition;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin/tool";
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
import { readFile } from "fs/promises";
|
|
4
|
+
import { join, dirname } from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { parse } from "smol-toml";
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
export const createConductorCommand = (options) => (ctx) => tool({
|
|
10
|
+
description: options.description,
|
|
11
|
+
args: options.args || {},
|
|
12
|
+
async execute(args) {
|
|
13
|
+
// 1. Setup Check
|
|
14
|
+
if (options.requiresSetup !== false) {
|
|
15
|
+
const conductorDir = join(ctx.directory, "conductor");
|
|
16
|
+
if (!existsSync(join(conductorDir, "product.md"))) {
|
|
17
|
+
return "Conductor is not set up. Please run `conductor_setup`.";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
// 2. Load Prompt from TOML
|
|
21
|
+
const promptPath = join(__dirname, "../prompts", options.name);
|
|
22
|
+
let promptText = "";
|
|
23
|
+
try {
|
|
24
|
+
const content = await readFile(promptPath, "utf-8");
|
|
25
|
+
const parsed = parse(content);
|
|
26
|
+
promptText = parsed.prompt;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
throw new Error(`Failed to load prompt from ${promptPath}: ${error}`);
|
|
30
|
+
}
|
|
31
|
+
// 3. Prepare Replacements
|
|
32
|
+
const replacements = {
|
|
33
|
+
isOMOActive: ctx.isOMOActive ? "true" : "false",
|
|
34
|
+
templatesDir: join(dirname(dirname(__dirname)), "dist/templates") // Fixing template path for setup
|
|
35
|
+
};
|
|
36
|
+
// 4. Inject Additional Context (e.g. from args)
|
|
37
|
+
if (options.additionalContext) {
|
|
38
|
+
const extra = await options.additionalContext(ctx, args);
|
|
39
|
+
Object.assign(replacements, extra);
|
|
40
|
+
}
|
|
41
|
+
// 5. Apply Replacements
|
|
42
|
+
for (const [key, value] of Object.entries(replacements)) {
|
|
43
|
+
promptText = promptText.replaceAll(`{{${key}}}`, value || "");
|
|
44
|
+
}
|
|
45
|
+
return promptText;
|
|
46
|
+
},
|
|
47
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-conductor-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"description": "Conductor plugin for OpenCode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": "derekbar90/opencode-conductor",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"scripts": {
|
|
31
31
|
"postinstall": "node scripts/postinstall.cjs",
|
|
32
32
|
"build": "tsc && npm run copy-prompts && npm run copy-templates",
|
|
33
|
-
"copy-prompts": "mkdir -p dist/prompts && cp src/prompts/*.toml src/prompts/*.md dist/prompts/ && mkdir -p dist/prompts/agent && cp src/prompts/agent/*.md dist/prompts/agent/ && mkdir -p dist/prompts/commands && cp src/prompts/commands/*.md dist/prompts/commands/",
|
|
33
|
+
"copy-prompts": "mkdir -p dist/prompts && cp src/prompts/*.toml src/prompts/*.md dist/prompts/ && mkdir -p dist/prompts/agent && cp src/prompts/agent/*.md dist/prompts/agent/ && mkdir -p dist/prompts/commands && cp src/prompts/commands/*.md dist/prompts/commands/ && mkdir -p dist/prompts/strategies && cp src/prompts/strategies/*.md dist/prompts/strategies/",
|
|
34
34
|
"copy-templates": "mkdir -p dist/templates && cp -r src/templates/* dist/templates/",
|
|
35
35
|
"prepublishOnly": "npm run build"
|
|
36
36
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function loadPrompt(filename: string, replacements?: Record<string, string>): Promise<string>;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { readFile } from "fs/promises";
|
|
2
|
-
import { join, dirname } from "path";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
|
-
import { parse } from "smol-toml";
|
|
5
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
-
const __dirname = dirname(__filename);
|
|
7
|
-
export async function loadPrompt(filename, replacements = {}) {
|
|
8
|
-
// Resolve path relative to this file.
|
|
9
|
-
// Structure: dist/utils/promptLoader.js -> dist/prompts/filename.toml
|
|
10
|
-
const promptPath = join(__dirname, "../prompts", filename);
|
|
11
|
-
try {
|
|
12
|
-
const content = await readFile(promptPath, "utf-8");
|
|
13
|
-
const parsed = parse(content);
|
|
14
|
-
let promptText = parsed.prompt;
|
|
15
|
-
for (const [key, value] of Object.entries(replacements)) {
|
|
16
|
-
promptText = promptText.replaceAll(`{{${key}}}`, value || "");
|
|
17
|
-
}
|
|
18
|
-
return promptText;
|
|
19
|
-
}
|
|
20
|
-
catch (error) {
|
|
21
|
-
throw new Error(`Failed to load prompt from ${promptPath}: ${error}`);
|
|
22
|
-
}
|
|
23
|
-
}
|