@codemcp/workflows 6.7.0 → 6.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/package.json +2 -2
- package/packages/cli/dist/{dist-QQCAQVXJ.js → dist-WVNXA2PS.js} +183 -19
- package/packages/cli/dist/index.js +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/core/package.json +1 -1
- package/packages/docs/package.json +1 -1
- package/packages/mcp-server/dist/index.d.ts +17 -0
- package/packages/mcp-server/dist/index.js +187 -19
- package/packages/mcp-server/package.json +1 -1
- package/packages/opencode-plugin/dist/index.js +232 -68
- package/packages/opencode-plugin/package.json +1 -1
- package/packages/opencode-tui-plugin/package.json +3 -1
- package/packages/visualizer/package.json +1 -1
|
@@ -6505,6 +6505,10 @@ var PluginRegistry = class {
|
|
|
6505
6505
|
}
|
|
6506
6506
|
};
|
|
6507
6507
|
|
|
6508
|
+
// src/plugin-system/beads-plugin.ts
|
|
6509
|
+
import { watch } from "fs";
|
|
6510
|
+
import { join as join8 } from "path";
|
|
6511
|
+
|
|
6508
6512
|
// src/components/beads/beads-task-backend-client.ts
|
|
6509
6513
|
import { execSync as execSync5 } from "child_process";
|
|
6510
6514
|
var defaultLogger7 = createLogger("BeadsTaskBackendClient");
|
|
@@ -6665,6 +6669,116 @@ var BeadsTaskBackendClient = class {
|
|
|
6665
6669
|
}
|
|
6666
6670
|
};
|
|
6667
6671
|
|
|
6672
|
+
// src/components/beads/beads-plan-syncer.ts
|
|
6673
|
+
import { readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
6674
|
+
import { join as join7 } from "path";
|
|
6675
|
+
var defaultLogger8 = createLogger("BeadsPlanSyncer");
|
|
6676
|
+
var BeadsPlanSyncer = class {
|
|
6677
|
+
logger;
|
|
6678
|
+
constructor(logger24) {
|
|
6679
|
+
this.logger = logger24 ?? defaultLogger8;
|
|
6680
|
+
}
|
|
6681
|
+
/**
|
|
6682
|
+
* Sync the given plan file with the latest beads tasks.
|
|
6683
|
+
*
|
|
6684
|
+
* No-ops when the plan file doesn't exist yet, when no phase IDs are
|
|
6685
|
+
* resolved, or when .beads/issues.jsonl is absent. Never throws.
|
|
6686
|
+
*/
|
|
6687
|
+
async sync(planFilePath, projectPath) {
|
|
6688
|
+
try {
|
|
6689
|
+
const issues = await this.readIssues(projectPath);
|
|
6690
|
+
if (issues === null) {
|
|
6691
|
+
return;
|
|
6692
|
+
}
|
|
6693
|
+
let planContent;
|
|
6694
|
+
try {
|
|
6695
|
+
planContent = await readFile4(planFilePath, "utf-8");
|
|
6696
|
+
} catch (err) {
|
|
6697
|
+
if (err.code === "ENOENT") return;
|
|
6698
|
+
throw err;
|
|
6699
|
+
}
|
|
6700
|
+
const updated = this.updatePlanContent(planContent, issues);
|
|
6701
|
+
if (updated !== planContent) {
|
|
6702
|
+
await writeFile4(planFilePath, updated, "utf-8");
|
|
6703
|
+
this.logger.debug("Plan file synced with beads tasks", {
|
|
6704
|
+
planFilePath
|
|
6705
|
+
});
|
|
6706
|
+
}
|
|
6707
|
+
} catch (error) {
|
|
6708
|
+
this.logger.warn("BeadsPlanSyncer: sync failed", {
|
|
6709
|
+
error: error instanceof Error ? error.message : String(error),
|
|
6710
|
+
planFilePath,
|
|
6711
|
+
projectPath
|
|
6712
|
+
});
|
|
6713
|
+
}
|
|
6714
|
+
}
|
|
6715
|
+
/**
|
|
6716
|
+
* Read and parse .beads/issues.jsonl.
|
|
6717
|
+
* Returns null if the file doesn't exist.
|
|
6718
|
+
*/
|
|
6719
|
+
async readIssues(projectPath) {
|
|
6720
|
+
const jsonlPath = join7(projectPath, ".beads", "issues.jsonl");
|
|
6721
|
+
let raw;
|
|
6722
|
+
try {
|
|
6723
|
+
raw = await readFile4(jsonlPath, "utf-8");
|
|
6724
|
+
} catch (err) {
|
|
6725
|
+
if (err.code === "ENOENT") return null;
|
|
6726
|
+
throw err;
|
|
6727
|
+
}
|
|
6728
|
+
const issues = [];
|
|
6729
|
+
for (const line of raw.split("\n")) {
|
|
6730
|
+
const trimmed = line.trim();
|
|
6731
|
+
if (!trimmed) continue;
|
|
6732
|
+
try {
|
|
6733
|
+
issues.push(JSON.parse(trimmed));
|
|
6734
|
+
} catch {
|
|
6735
|
+
}
|
|
6736
|
+
}
|
|
6737
|
+
return issues;
|
|
6738
|
+
}
|
|
6739
|
+
/**
|
|
6740
|
+
* Find direct children of a given phase task ID.
|
|
6741
|
+
* A child issue has a parent-child dependency pointing to phaseId.
|
|
6742
|
+
*/
|
|
6743
|
+
getChildTasks(issues, phaseId) {
|
|
6744
|
+
return issues.filter(
|
|
6745
|
+
(issue) => issue.dependencies?.some(
|
|
6746
|
+
(dep) => dep.depends_on_id === phaseId && dep.type === "parent-child"
|
|
6747
|
+
)
|
|
6748
|
+
);
|
|
6749
|
+
}
|
|
6750
|
+
/**
|
|
6751
|
+
* Rewrite all synced task sections in the plan content.
|
|
6752
|
+
*/
|
|
6753
|
+
updatePlanContent(content, issues) {
|
|
6754
|
+
const phaseSectionRe = /(## [^\n]+\n<!-- beads-phase-id: (?!TBD)([^\s>]+) -->)([\s\S]*?)(### Tasks\n)([\s\S]*?)(?=\n## |\n### |$)/g;
|
|
6755
|
+
return content.replace(
|
|
6756
|
+
phaseSectionRe,
|
|
6757
|
+
(_match, phaseHeaderAndId, phaseId, betweenIdAndTasks, tasksHeader, _existingBody) => {
|
|
6758
|
+
const children = this.getChildTasks(issues, phaseId);
|
|
6759
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
6760
|
+
const header = `<!-- beads-synced: ${today} -->
|
|
6761
|
+
*Auto-synced \u2014 do not edit here, use \`bd\` CLI instead.*
|
|
6762
|
+
`;
|
|
6763
|
+
let tasksBody;
|
|
6764
|
+
if (children.length === 0) {
|
|
6765
|
+
tasksBody = `${header}
|
|
6766
|
+
`;
|
|
6767
|
+
} else {
|
|
6768
|
+
const taskLines = children.map((task) => {
|
|
6769
|
+
const checkbox = task.status === "closed" ? "[x]" : "[ ]";
|
|
6770
|
+
return `- ${checkbox} \`${task.id}\` ${task.title}`;
|
|
6771
|
+
}).join("\n");
|
|
6772
|
+
tasksBody = `${header}
|
|
6773
|
+
${taskLines}
|
|
6774
|
+
`;
|
|
6775
|
+
}
|
|
6776
|
+
return `${phaseHeaderAndId}${betweenIdAndTasks}${tasksHeader}${tasksBody}`;
|
|
6777
|
+
}
|
|
6778
|
+
);
|
|
6779
|
+
}
|
|
6780
|
+
};
|
|
6781
|
+
|
|
6668
6782
|
// src/plugin-system/beads-plugin.ts
|
|
6669
6783
|
var BeadsPlugin = class {
|
|
6670
6784
|
projectPath;
|
|
@@ -6673,6 +6787,17 @@ var BeadsPlugin = class {
|
|
|
6673
6787
|
planManager;
|
|
6674
6788
|
logger;
|
|
6675
6789
|
loggerFactory;
|
|
6790
|
+
planSyncer;
|
|
6791
|
+
/**
|
|
6792
|
+
* Plan file path captured from the most recent hook context.
|
|
6793
|
+
* Set by afterStartDevelopment and beforePhaseTransition so the watcher
|
|
6794
|
+
* always has the correct path without touching GitManager.
|
|
6795
|
+
*/
|
|
6796
|
+
activePlanFilePath = null;
|
|
6797
|
+
/** Debounce timer for the JSONL file watcher */
|
|
6798
|
+
syncDebounceTimer = null;
|
|
6799
|
+
/** Active fs.watch watcher (closed on process exit) */
|
|
6800
|
+
jsonlWatcher = null;
|
|
6676
6801
|
constructor(options) {
|
|
6677
6802
|
this.projectPath = options.projectPath;
|
|
6678
6803
|
this.loggerFactory = options.loggerFactory;
|
|
@@ -6686,6 +6811,13 @@ var BeadsPlugin = class {
|
|
|
6686
6811
|
options.loggerFactory ? options.loggerFactory("BeadsTaskBackendClient") : void 0
|
|
6687
6812
|
);
|
|
6688
6813
|
this.planManager = new PlanManager();
|
|
6814
|
+
this.planSyncer = new BeadsPlanSyncer(
|
|
6815
|
+
options.loggerFactory ? options.loggerFactory("BeadsPlanSyncer") : void 0
|
|
6816
|
+
);
|
|
6817
|
+
process.once("exit", () => {
|
|
6818
|
+
this.jsonlWatcher?.close();
|
|
6819
|
+
});
|
|
6820
|
+
this.startJsonlWatcher();
|
|
6689
6821
|
this.logger.debug("BeadsPlugin initialized", {
|
|
6690
6822
|
projectPath: this.projectPath
|
|
6691
6823
|
});
|
|
@@ -6720,6 +6852,7 @@ var BeadsPlugin = class {
|
|
|
6720
6852
|
* Replaces validateBeadsTaskCompletion() method from proceed-to-phase.ts
|
|
6721
6853
|
*/
|
|
6722
6854
|
async handleBeforePhaseTransition(context, currentPhase, targetPhase) {
|
|
6855
|
+
this.activePlanFilePath = context.planFilePath;
|
|
6723
6856
|
this.logger.info(
|
|
6724
6857
|
"BeadsPlugin: Validating task completion before phase transition",
|
|
6725
6858
|
{
|
|
@@ -6762,6 +6895,7 @@ var BeadsPlugin = class {
|
|
|
6762
6895
|
* Implements graceful degradation: continues app operation even if beads operations fail
|
|
6763
6896
|
*/
|
|
6764
6897
|
async handleAfterStartDevelopment(context, args, _result) {
|
|
6898
|
+
this.activePlanFilePath = context.planFilePath;
|
|
6765
6899
|
this.logger.info("BeadsPlugin: Setting up beads integration", {
|
|
6766
6900
|
conversationId: context.conversationId,
|
|
6767
6901
|
workflow: args.workflow,
|
|
@@ -6997,8 +7131,8 @@ Complete tasks: \`bd close <id>\``;
|
|
|
6997
7131
|
*/
|
|
6998
7132
|
async extractPhaseTaskIdFromPlanFile(planFilePath, phase) {
|
|
6999
7133
|
try {
|
|
7000
|
-
const { readFile:
|
|
7001
|
-
const content = await
|
|
7134
|
+
const { readFile: readFile6 } = await import("fs/promises");
|
|
7135
|
+
const content = await readFile6(planFilePath, "utf-8");
|
|
7002
7136
|
const phaseName = this.capitalizePhase(phase);
|
|
7003
7137
|
const phaseHeader = `## ${phaseName}`;
|
|
7004
7138
|
const lines = content.split("\n");
|
|
@@ -7152,6 +7286,40 @@ Complete tasks: \`bd close <id>\``;
|
|
|
7152
7286
|
);
|
|
7153
7287
|
}
|
|
7154
7288
|
}
|
|
7289
|
+
/**
|
|
7290
|
+
* Start watching the .beads/ directory for changes to issues.jsonl.
|
|
7291
|
+
* Watching the directory (not the file) means the watcher works even when
|
|
7292
|
+
* issues.jsonl doesn't exist yet. On change, debounces 300ms then syncs.
|
|
7293
|
+
*/
|
|
7294
|
+
startJsonlWatcher() {
|
|
7295
|
+
const beadsDir = join8(this.projectPath, ".beads");
|
|
7296
|
+
try {
|
|
7297
|
+
this.jsonlWatcher = watch(beadsDir, (_event, filename) => {
|
|
7298
|
+
if (filename !== "issues.jsonl") return;
|
|
7299
|
+
if (this.syncDebounceTimer) {
|
|
7300
|
+
clearTimeout(this.syncDebounceTimer);
|
|
7301
|
+
}
|
|
7302
|
+
this.syncDebounceTimer = setTimeout(() => {
|
|
7303
|
+
this.syncDebounceTimer = null;
|
|
7304
|
+
if (!this.activePlanFilePath) return;
|
|
7305
|
+
this.planSyncer.sync(this.activePlanFilePath, this.projectPath).catch((err) => {
|
|
7306
|
+
this.logger.warn(
|
|
7307
|
+
"BeadsPlugin: Error during watcher-triggered plan sync",
|
|
7308
|
+
{
|
|
7309
|
+
error: err instanceof Error ? err.message : String(err)
|
|
7310
|
+
}
|
|
7311
|
+
);
|
|
7312
|
+
});
|
|
7313
|
+
}, 300);
|
|
7314
|
+
});
|
|
7315
|
+
this.logger.info("BeadsPlugin: Started JSONL file watcher", { beadsDir });
|
|
7316
|
+
} catch (error) {
|
|
7317
|
+
this.logger.warn("BeadsPlugin: Could not start JSONL file watcher", {
|
|
7318
|
+
error: error instanceof Error ? error.message : String(error),
|
|
7319
|
+
beadsDir
|
|
7320
|
+
});
|
|
7321
|
+
}
|
|
7322
|
+
}
|
|
7155
7323
|
/**
|
|
7156
7324
|
* Extract Goal section content from plan file
|
|
7157
7325
|
* Returns the goal content if it exists and is meaningful, otherwise undefined
|
|
@@ -7193,10 +7361,10 @@ Complete tasks: \`bd close <id>\``;
|
|
|
7193
7361
|
*/
|
|
7194
7362
|
async updatePlanFileWithPhaseTaskIds(planFilePath, phaseTasks) {
|
|
7195
7363
|
try {
|
|
7196
|
-
const { readFile:
|
|
7364
|
+
const { readFile: readFile6, writeFile: writeFile6 } = await import("fs/promises");
|
|
7197
7365
|
let content;
|
|
7198
7366
|
try {
|
|
7199
|
-
content = await
|
|
7367
|
+
content = await readFile6(planFilePath, "utf-8");
|
|
7200
7368
|
} catch (error) {
|
|
7201
7369
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
7202
7370
|
this.logger.warn("BeadsPlugin: Failed to read plan file for update", {
|
|
@@ -7229,7 +7397,7 @@ Complete tasks: \`bd close <id>\``;
|
|
|
7229
7397
|
);
|
|
7230
7398
|
}
|
|
7231
7399
|
try {
|
|
7232
|
-
await
|
|
7400
|
+
await writeFile6(planFilePath, content, "utf-8");
|
|
7233
7401
|
} catch (error) {
|
|
7234
7402
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
7235
7403
|
this.logger.warn("BeadsPlugin: Failed to write updated plan file", {
|
|
@@ -8506,7 +8674,7 @@ Summarize findings and ask user if ready to proceed.`;
|
|
|
8506
8674
|
// src/tool-handlers/start-development.ts
|
|
8507
8675
|
import { basename as basename4 } from "path";
|
|
8508
8676
|
import { readFileSync, writeFileSync, existsSync as existsSync3, mkdirSync } from "fs";
|
|
8509
|
-
import { readFile as
|
|
8677
|
+
import { readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
8510
8678
|
import { resolve as resolve3 } from "path";
|
|
8511
8679
|
var StartDevelopmentHandler = class extends BaseToolHandler {
|
|
8512
8680
|
projectDocsManager = null;
|
|
@@ -8626,7 +8794,7 @@ var StartDevelopmentHandler = class extends BaseToolHandler {
|
|
|
8626
8794
|
};
|
|
8627
8795
|
if (context.pluginRegistry) {
|
|
8628
8796
|
try {
|
|
8629
|
-
const originalContent = await
|
|
8797
|
+
const originalContent = await readFile5(
|
|
8630
8798
|
conversationContext.planFilePath,
|
|
8631
8799
|
"utf-8"
|
|
8632
8800
|
);
|
|
@@ -8637,7 +8805,7 @@ var StartDevelopmentHandler = class extends BaseToolHandler {
|
|
|
8637
8805
|
originalContent
|
|
8638
8806
|
);
|
|
8639
8807
|
if (modifiedContent && modifiedContent !== originalContent) {
|
|
8640
|
-
await
|
|
8808
|
+
await writeFile5(
|
|
8641
8809
|
conversationContext.planFilePath,
|
|
8642
8810
|
modifiedContent,
|
|
8643
8811
|
"utf-8"
|
|
@@ -9243,7 +9411,7 @@ import { z as z3 } from "zod";
|
|
|
9243
9411
|
// src/version-info.ts
|
|
9244
9412
|
import { execSync as execSync6 } from "child_process";
|
|
9245
9413
|
import { readFileSync as readFileSync2 } from "fs";
|
|
9246
|
-
import { join as
|
|
9414
|
+
import { join as join10, dirname as dirname6 } from "path";
|
|
9247
9415
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
9248
9416
|
var logger17 = createLogger("VersionInfo");
|
|
9249
9417
|
var BUILD_TIME_VERSION = null;
|
|
@@ -9251,8 +9419,8 @@ function getVersionFromPackageJson() {
|
|
|
9251
9419
|
try {
|
|
9252
9420
|
const currentDir = dirname6(fileURLToPath4(import.meta.url));
|
|
9253
9421
|
const packageJsonPaths = [
|
|
9254
|
-
|
|
9255
|
-
|
|
9422
|
+
join10(currentDir, "..", "package.json"),
|
|
9423
|
+
join10(currentDir, "..", "..", "..", "package.json")
|
|
9256
9424
|
];
|
|
9257
9425
|
for (const packageJsonPath of packageJsonPaths) {
|
|
9258
9426
|
try {
|
|
@@ -9713,11 +9881,11 @@ function createToolRegistry() {
|
|
|
9713
9881
|
}
|
|
9714
9882
|
|
|
9715
9883
|
// src/resource-handlers/development-plan.ts
|
|
9716
|
-
var
|
|
9884
|
+
var defaultLogger9 = createLogger("DevelopmentPlanResourceHandler");
|
|
9717
9885
|
var DevelopmentPlanResourceHandler = class {
|
|
9718
9886
|
logger;
|
|
9719
9887
|
constructor(logger24) {
|
|
9720
|
-
this.logger = logger24 ??
|
|
9888
|
+
this.logger = logger24 ?? defaultLogger9;
|
|
9721
9889
|
}
|
|
9722
9890
|
async handle(uri, context) {
|
|
9723
9891
|
if (context.loggerFactory) {
|
|
@@ -9741,11 +9909,11 @@ var DevelopmentPlanResourceHandler = class {
|
|
|
9741
9909
|
};
|
|
9742
9910
|
|
|
9743
9911
|
// src/resource-handlers/conversation-state.ts
|
|
9744
|
-
var
|
|
9912
|
+
var defaultLogger10 = createLogger("ConversationStateResourceHandler");
|
|
9745
9913
|
var ConversationStateResourceHandler = class {
|
|
9746
9914
|
logger;
|
|
9747
9915
|
constructor(logger24) {
|
|
9748
|
-
this.logger = logger24 ??
|
|
9916
|
+
this.logger = logger24 ?? defaultLogger10;
|
|
9749
9917
|
}
|
|
9750
9918
|
async handle(uri, context) {
|
|
9751
9919
|
if (context.loggerFactory) {
|
|
@@ -9778,11 +9946,11 @@ var ConversationStateResourceHandler = class {
|
|
|
9778
9946
|
import fs5 from "fs";
|
|
9779
9947
|
import path5 from "path";
|
|
9780
9948
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
9781
|
-
var
|
|
9949
|
+
var defaultLogger11 = createLogger("WorkflowResourceHandler");
|
|
9782
9950
|
var WorkflowResourceHandler = class {
|
|
9783
9951
|
logger;
|
|
9784
9952
|
constructor(logger24) {
|
|
9785
|
-
this.logger = logger24 ??
|
|
9953
|
+
this.logger = logger24 ?? defaultLogger11;
|
|
9786
9954
|
}
|
|
9787
9955
|
async handle(uri, context) {
|
|
9788
9956
|
if (context.loggerFactory) {
|
|
@@ -9870,11 +10038,11 @@ var WorkflowResourceHandler = class {
|
|
|
9870
10038
|
};
|
|
9871
10039
|
|
|
9872
10040
|
// src/resource-handlers/system-prompt.ts
|
|
9873
|
-
var
|
|
10041
|
+
var defaultLogger12 = createLogger("SystemPromptResourceHandler");
|
|
9874
10042
|
var SystemPromptResourceHandler = class {
|
|
9875
10043
|
logger;
|
|
9876
10044
|
constructor(logger24) {
|
|
9877
|
-
this.logger = logger24 ??
|
|
10045
|
+
this.logger = logger24 ?? defaultLogger12;
|
|
9878
10046
|
}
|
|
9879
10047
|
async handle(uri, context) {
|
|
9880
10048
|
if (context.loggerFactory) {
|