@codemcp/workflows-opencode 6.11.1 → 6.13.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/README.md CHANGED
@@ -90,6 +90,18 @@ When the env var is set, workflow hooks are skipped and tools throw a clear erro
90
90
 
91
91
  **When unset**, workflows are active for all agents (default behavior).
92
92
 
93
+ ### Auto-Compaction
94
+
95
+ When transitioning to a new phase via `proceed_to_phase`, the plugin automatically triggers a session compaction (summarize) to clear prior-phase context from the LLM window. This is enabled by default.
96
+
97
+ Set `WORKFLOW_AUTO_COMPACT=false` to disable this behavior:
98
+
99
+ ```bash
100
+ WORKFLOW_AUTO_COMPACT=false npx opencode
101
+ ```
102
+
103
+ **When unset or any value other than `false`**, compaction runs on every successful phase transition (default behavior).
104
+
93
105
  ### Per-Agent Behavior
94
106
 
95
107
  - **Agent in filter**: Workflow instructions are injected on every message, tools work normally
package/dist/index.d.ts CHANGED
@@ -65,9 +65,26 @@ type ToolDefinition = {
65
65
  args: z.ZodRawShape;
66
66
  execute(args: unknown, context: ToolContext): Promise<string>;
67
67
  };
68
+ type SessionCompactedEvent = {
69
+ type: 'session.compacted';
70
+ properties: {
71
+ sessionID: string;
72
+ };
73
+ };
74
+ type SessionIdleEvent = {
75
+ type: 'session.idle';
76
+ properties: {
77
+ sessionID: string;
78
+ };
79
+ };
80
+ type OtherEvent = {
81
+ type: string;
82
+ properties: Record<string, unknown>;
83
+ };
84
+ type BusEvent = SessionCompactedEvent | SessionIdleEvent | OtherEvent;
68
85
  interface Hooks {
69
86
  event?: (input: {
70
- event: unknown;
87
+ event: BusEvent;
71
88
  }) => Promise<void>;
72
89
  config?: (input: unknown) => Promise<void>;
73
90
  tool?: {
@@ -217,4 +234,4 @@ declare const _default: {
217
234
  server: Plugin;
218
235
  };
219
236
 
220
- export { type Hooks, type Message, type Model, type Part, type Plugin, type PluginInput, type PluginModule, type Project, type ToolContext, type ToolDefinition, type UserMessage, WorkflowsPlugin, _default as default };
237
+ export { type BusEvent, type Hooks, type Message, type Model, type OtherEvent, type Part, type Plugin, type PluginInput, type PluginModule, type Project, type SessionCompactedEvent, type SessionIdleEvent, type ToolContext, type ToolDefinition, type UserMessage, WorkflowsPlugin, _default as default };
package/dist/index.js CHANGED
@@ -16902,7 +16902,7 @@ var PlanManager = class {
16902
16902
  if (workflowName === "custom") {
16903
16903
  return void 0;
16904
16904
  }
16905
- return `https://mrsimpson.github.io/responsible-vibe-mcp/workflows/${workflowName}`;
16905
+ return `https://codemcp.github.io/workflows/workflows/${workflowName}`;
16906
16906
  }
16907
16907
  /**
16908
16908
  * Generate base instructions for the LLM after a workflow is started.
@@ -18663,9 +18663,13 @@ var InstructionGenerator = class {
18663
18663
  const { phase, conversationContext, allowedFilePatterns } = context;
18664
18664
  const phaseName = capitalizePhase(phase);
18665
18665
  let workflowSection = `---
18666
- **Read \`${conversationContext.planFilePath}\`** for context.
18667
- - Focus on "${phaseName}" tasks, log decisions in "Key Decisions"
18668
- - Do NOT use other task/todo tools - use only the plan file for task tracking`;
18666
+ ### YOU MUST FOLLOW THESE INSTRUCTIONS:
18667
+
18668
+ **IMPORTANT: Read \`${conversationContext.planFilePath}\`** for context.
18669
+
18670
+ **ACTION REQUIRED: Focus on "${phaseName}" tasks** and log decisions in "Key Decisions"
18671
+
18672
+ **CRITICAL: Do NOT use other task/todo tools** - use only the plan file for task tracking`;
18669
18673
  if (allowedFilePatterns && allowedFilePatterns.length > 0 && !allowedFilePatterns.includes("**/*") && !allowedFilePatterns.includes("*")) {
18670
18674
  workflowSection += `
18671
18675
  - Files allowed: \`${allowedFilePatterns.join("`, `")}\``;
@@ -21453,7 +21457,7 @@ Then retry \`start_development\`.`;
21453
21457
  if (workflowName === "custom") {
21454
21458
  return void 0;
21455
21459
  }
21456
- return `https://mrsimpson.github.io/responsible-vibe-mcp/workflows/${workflowName}`;
21460
+ return `https://codemcp.github.io/workflows/workflows/${workflowName}`;
21457
21461
  }
21458
21462
  /**
21459
21463
  * Get the current git branch for a project
@@ -27030,7 +27034,7 @@ var PlanManager2 = class {
27030
27034
  if (workflowName === "custom") {
27031
27035
  return void 0;
27032
27036
  }
27033
- return `https://mrsimpson.github.io/responsible-vibe-mcp/workflows/${workflowName}`;
27037
+ return `https://codemcp.github.io/workflows/workflows/${workflowName}`;
27034
27038
  }
27035
27039
  /**
27036
27040
  * Generate base instructions for the LLM after a workflow is started.
@@ -28057,9 +28061,13 @@ var InstructionGenerator2 = class {
28057
28061
  const { phase, conversationContext, allowedFilePatterns } = context;
28058
28062
  const phaseName = capitalizePhase3(phase);
28059
28063
  let workflowSection = `---
28060
- **Read \`${conversationContext.planFilePath}\`** for context.
28061
- - Focus on "${phaseName}" tasks, log decisions in "Key Decisions"
28062
- - Do NOT use other task/todo tools - use only the plan file for task tracking`;
28064
+ ### YOU MUST FOLLOW THESE INSTRUCTIONS:
28065
+
28066
+ **IMPORTANT: Read \`${conversationContext.planFilePath}\`** for context.
28067
+
28068
+ **ACTION REQUIRED: Focus on "${phaseName}" tasks** and log decisions in "Key Decisions"
28069
+
28070
+ **CRITICAL: Do NOT use other task/todo tools** - use only the plan file for task tracking`;
28063
28071
  if (allowedFilePatterns && allowedFilePatterns.length > 0 && !allowedFilePatterns.includes("**/*") && !allowedFilePatterns.includes("*")) {
28064
28072
  workflowSection += `
28065
28073
  - Files allowed: \`${allowedFilePatterns.join("`, `")}\``;
@@ -28202,17 +28210,25 @@ function createProceedToPhaseTool(getServerContext, setBufferedInstructions, cli
28202
28210
  plan_file_path: data.plan_file_path,
28203
28211
  allowed_file_patterns: data.allowed_file_patterns
28204
28212
  });
28205
- const model = getModel();
28206
- client.session.summarize({
28207
- path: { id: context.sessionID },
28208
- ...model ? { body: model } : {}
28209
- }).catch(() => {
28210
- });
28211
- logger37.info("Triggered compaction after phase transition", {
28212
- phase: data.phase,
28213
- sessionID: context.sessionID,
28214
- hasModel: !!model
28215
- });
28213
+ const autoCompact = process.env["WORKFLOW_AUTO_COMPACT"]?.trim()?.toLowerCase();
28214
+ if (autoCompact !== "false") {
28215
+ const model = getModel();
28216
+ client.session.summarize({
28217
+ path: { id: context.sessionID },
28218
+ ...model ? { body: model } : {}
28219
+ }).catch(() => {
28220
+ });
28221
+ logger37.info("Triggered compaction after phase transition", {
28222
+ phase: data.phase,
28223
+ sessionID: context.sessionID,
28224
+ hasModel: !!model
28225
+ });
28226
+ } else {
28227
+ logger37.debug("Skipped compaction: WORKFLOW_AUTO_COMPACT=false", {
28228
+ phase: data.phase,
28229
+ sessionID: context.sessionID
28230
+ });
28231
+ }
28216
28232
  const lines = [];
28217
28233
  lines.push(`Transitioned to: ${data.phase}`);
28218
28234
  if (data.transition_reason) {
@@ -28597,6 +28613,8 @@ var WorkflowsPlugin = async (input) => {
28597
28613
  let currentSessionId = null;
28598
28614
  let lastKnownSessionId = null;
28599
28615
  let bufferedInstructions = null;
28616
+ let postCompactionSession = null;
28617
+ let postCompactionMessagePending = false;
28600
28618
  let lastKnownModel = null;
28601
28619
  function setBufferedInstructions(result) {
28602
28620
  bufferedInstructions = {
@@ -28684,6 +28702,13 @@ var WorkflowsPlugin = async (input) => {
28684
28702
  if (hookInput.model) {
28685
28703
  lastKnownModel = hookInput.model;
28686
28704
  }
28705
+ if (postCompactionMessagePending) {
28706
+ postCompactionMessagePending = false;
28707
+ logger37.debug(
28708
+ "chat.message: skipping synthetic part for post-compaction instructions message"
28709
+ );
28710
+ return;
28711
+ }
28687
28712
  if (!isAgentEnabled(hookInput.agent)) {
28688
28713
  logger37.debug(
28689
28714
  "chat.message: Agent not enabled \u2014 injecting tool suppression",
@@ -28822,8 +28847,10 @@ ACTION REQUIRED: Use transition_phase tool to move to a phase that allows editin
28822
28847
  },
28823
28848
  /**
28824
28849
  * Hook 3: experimental.session.compacting
28825
- * Fires when session is being compacted. We provide minimal guidance on what
28826
- * to preserve and instruct the summary to end with phase continuation.
28850
+ * Fires when session is being compacted. We provide full phase instructions
28851
+ * so the compaction summary is self-sufficient the AI knows exactly what
28852
+ * to continue even if the chat.message hook doesn't fire for the synthetic
28853
+ * auto-compaction "continue" message.
28827
28854
  */
28828
28855
  "experimental.session.compacting": async (hookInput, output) => {
28829
28856
  logger37.debug("experimental.session.compacting hook fired", {
@@ -28834,13 +28861,103 @@ ACTION REQUIRED: Use transition_phase tool to move to a phase that allows editin
28834
28861
  logger37.debug("No active workflow - skipping compaction guidance");
28835
28862
  return;
28836
28863
  }
28864
+ let phaseInstructions = null;
28865
+ try {
28866
+ const serverContext = await getServerContext();
28867
+ const handler = new WhatsNextHandler();
28868
+ const handlerResult = await handler.handle({}, serverContext);
28869
+ if (handlerResult.success && handlerResult.data) {
28870
+ phaseInstructions = stripWhatsNextReferences(
28871
+ handlerResult.data.instructions
28872
+ );
28873
+ }
28874
+ } catch (_err) {
28875
+ }
28837
28876
  output.context.push(
28838
28877
  "Preserve: user intents, key decisions, significant changes and the reasoning why they were made. Remove tool calls, intermediate thoughts, and minor details."
28839
28878
  );
28840
- output.context.push(
28841
- `End summary with: "Continue ${state.phase} phase. ${state.phaseDescription || ""}"`
28842
- );
28843
- logger37.info("Injected compaction guidance", { phase: state.phase });
28879
+ if (phaseInstructions) {
28880
+ output.context.push(
28881
+ `Current workflow phase: ${state.phase}. After compaction, resume with full phase context:
28882
+
28883
+ ${phaseInstructions}`
28884
+ );
28885
+ } else {
28886
+ output.context.push(
28887
+ `End summary with: "Continue ${state.phase} phase. ${state.phaseDescription || ""}"`
28888
+ );
28889
+ }
28890
+ logger37.info("Injected compaction guidance", {
28891
+ phase: state.phase,
28892
+ fullInstructions: phaseInstructions !== null
28893
+ });
28894
+ },
28895
+ /**
28896
+ * Hook 4: event
28897
+ * Listens for bus events. When a session compaction completes we record it,
28898
+ * then when the session becomes idle we send a real user message so the
28899
+ * normal chat.message hook fires and injects phase instructions — giving the
28900
+ * AI full workflow context to continue after the compaction.
28901
+ *
28902
+ * We intentionally do NOT suppress the default synthetic "continue" message
28903
+ * (experimental.compaction.autocontinue). It may produce a first generic AI
28904
+ * response, but the idle trigger below ensures a proper phase-aware follow-up.
28905
+ */
28906
+ event: async ({ event }) => {
28907
+ logger37.debug("event hook fired", { type: event.type });
28908
+ if (event.type === "session.compacted") {
28909
+ postCompactionSession = event.properties.sessionID;
28910
+ logger37.info("session.compacted: pending phase-aware continue", {
28911
+ sessionID: postCompactionSession
28912
+ });
28913
+ return;
28914
+ }
28915
+ if (event.type === "session.idle" && postCompactionSession === event.properties.sessionID) {
28916
+ const sessionID = postCompactionSession;
28917
+ postCompactionSession = null;
28918
+ logger37.info(
28919
+ "session.idle after compaction: sending phase-aware continue",
28920
+ { sessionID }
28921
+ );
28922
+ await new Promise((resolve6) => setTimeout(resolve6, 500));
28923
+ let promptText = "Continue with the current phase.";
28924
+ let usedPhaseInstructions = false;
28925
+ try {
28926
+ const serverContext = await getServerContext();
28927
+ const handler = new WhatsNextHandler();
28928
+ const handlerResult = await handler.handle({}, serverContext);
28929
+ if (handlerResult.success && handlerResult.data) {
28930
+ const instructions = stripWhatsNextReferences(
28931
+ handlerResult.data.instructions
28932
+ );
28933
+ if (instructions.trim()) {
28934
+ promptText = instructions;
28935
+ usedPhaseInstructions = true;
28936
+ }
28937
+ }
28938
+ } catch (_err) {
28939
+ }
28940
+ if (usedPhaseInstructions) {
28941
+ postCompactionMessagePending = true;
28942
+ }
28943
+ try {
28944
+ const client = input.client;
28945
+ await client.session.promptAsync({
28946
+ path: { id: sessionID },
28947
+ body: {
28948
+ parts: [{ type: "text", text: promptText }]
28949
+ }
28950
+ });
28951
+ logger37.info("session.idle: phase-aware continue sent (async)", {
28952
+ sessionID
28953
+ });
28954
+ } catch (err) {
28955
+ logger37.error("session.idle: failed to send phase-aware continue", {
28956
+ sessionID,
28957
+ error: err instanceof Error ? err.message : String(err)
28958
+ });
28959
+ }
28960
+ }
28844
28961
  },
28845
28962
  /**
28846
28963
  * Custom tools - always registered to allow clear error messages.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemcp/workflows-opencode",
3
- "version": "6.11.1",
3
+ "version": "6.13.4",
4
4
  "description": "OpenCode plugin for structured development workflows",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -19,8 +19,8 @@
19
19
  "rimraf": "^6.0.1",
20
20
  "tsup": "^8.0.0",
21
21
  "vitest": "4.0.18",
22
- "@codemcp/workflows-server": "6.11.1",
23
- "@codemcp/workflows-core": "6.11.1"
22
+ "@codemcp/workflows-core": "6.13.4",
23
+ "@codemcp/workflows-server": "6.13.4"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "@anthropic-ai/sdk": "*"
@@ -39,7 +39,7 @@
39
39
  "license": "MIT",
40
40
  "repository": {
41
41
  "type": "git",
42
- "url": "https://github.com/mrsimpson/responsible-vibe-mcp"
42
+ "url": "https://github.com/codemcp/workflows"
43
43
  },
44
44
  "scripts": {
45
45
  "build": "tsup && pnpm copy-resources",
@@ -16,7 +16,7 @@ systemPrompt: |
16
16
 
17
17
  ## Available Tools
18
18
 
19
- **Workflow Navigation (responsible-vibe-mcp):**
19
+ **Workflow Navigation:**
20
20
  - `whats_next()`: Call this after EVERY user message to get phase-specific guidance
21
21
  - `proceed_to_phase()`: Move to the next phase when your work is complete (only when responsible)
22
22
 
@@ -45,7 +45,7 @@ llmSettings:
45
45
  reasoningEffort: medium
46
46
 
47
47
  mcpServers:
48
- workflows:
48
+ 'workflows':
49
49
  type: stdio
50
50
  command: npx
51
51
  args:
@@ -16,7 +16,7 @@ systemPrompt: |
16
16
 
17
17
  ## Available Tools
18
18
 
19
- **Workflow Navigation (responsible-vibe-mcp):**
19
+ **Workflow Navigation**
20
20
  - `whats_next()`: Call this after EVERY user message to get phase-specific guidance
21
21
  - `proceed_to_phase()`: Move to the next phase when your work is complete (only when responsible)
22
22
 
@@ -16,7 +16,7 @@ systemPrompt: |
16
16
 
17
17
  ## Available Tools
18
18
 
19
- **Workflow Navigation (responsible-vibe-mcp):**
19
+ **Workflow Navigation**
20
20
  - `whats_next()`: Call this after EVERY user message to get phase-specific guidance
21
21
  - `proceed_to_phase()`: Move to the next phase when your work is complete (only when responsible)
22
22
 
@@ -18,6 +18,6 @@ keywords:
18
18
  license: MIT
19
19
  metadata:
20
20
  version: '${VERSION}'
21
- repository: https://github.com/mrsimpson/responsible-vibe-mcp
21
+ repository: https://github.com/codemcp/workflows
22
22
  author: mrsimpson
23
23
  ---
@@ -8,7 +8,7 @@ description: >
8
8
  license: MIT
9
9
  metadata:
10
10
  version: '${VERSION}'
11
- repository: https://github.com/mrsimpson/responsible-vibe-mcp
11
+ repository: https://github.com/codemcp/workflows
12
12
  author: mrsimpson
13
13
  requires-mcp-servers:
14
14
  - name: workflows