agent-bober 0.6.2 → 0.7.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.
Files changed (145) hide show
  1. package/README.md +156 -28
  2. package/dist/cli/commands/eval.d.ts +2 -0
  3. package/dist/cli/commands/eval.d.ts.map +1 -1
  4. package/dist/cli/commands/eval.js +10 -0
  5. package/dist/cli/commands/eval.js.map +1 -1
  6. package/dist/cli/commands/init.d.ts.map +1 -1
  7. package/dist/cli/commands/init.js +181 -61
  8. package/dist/cli/commands/init.js.map +1 -1
  9. package/dist/cli/commands/plan.d.ts +2 -0
  10. package/dist/cli/commands/plan.d.ts.map +1 -1
  11. package/dist/cli/commands/plan.js +10 -0
  12. package/dist/cli/commands/plan.js.map +1 -1
  13. package/dist/cli/commands/run.d.ts +2 -0
  14. package/dist/cli/commands/run.d.ts.map +1 -1
  15. package/dist/cli/commands/run.js +10 -0
  16. package/dist/cli/commands/run.js.map +1 -1
  17. package/dist/cli/commands/sprint.d.ts +2 -0
  18. package/dist/cli/commands/sprint.d.ts.map +1 -1
  19. package/dist/cli/commands/sprint.js +10 -0
  20. package/dist/cli/commands/sprint.js.map +1 -1
  21. package/dist/cli/index.js +22 -2
  22. package/dist/cli/index.js.map +1 -1
  23. package/dist/config/schema.d.ts +160 -43
  24. package/dist/config/schema.d.ts.map +1 -1
  25. package/dist/config/schema.js +11 -7
  26. package/dist/config/schema.js.map +1 -1
  27. package/dist/contracts/sprint-contract.d.ts +8 -8
  28. package/dist/index.d.ts +8 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +8 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/mcp/index.d.ts +4 -0
  33. package/dist/mcp/index.d.ts.map +1 -0
  34. package/dist/mcp/index.js +4 -0
  35. package/dist/mcp/index.js.map +1 -0
  36. package/dist/mcp/run-manager.d.ts +47 -0
  37. package/dist/mcp/run-manager.d.ts.map +1 -0
  38. package/dist/mcp/run-manager.js +79 -0
  39. package/dist/mcp/run-manager.js.map +1 -0
  40. package/dist/mcp/server.d.ts +15 -0
  41. package/dist/mcp/server.d.ts.map +1 -0
  42. package/dist/mcp/server.js +107 -0
  43. package/dist/mcp/server.js.map +1 -0
  44. package/dist/mcp/tools/config.d.ts +2 -0
  45. package/dist/mcp/tools/config.d.ts.map +1 -0
  46. package/dist/mcp/tools/config.js +153 -0
  47. package/dist/mcp/tools/config.js.map +1 -0
  48. package/dist/mcp/tools/contracts.d.ts +2 -0
  49. package/dist/mcp/tools/contracts.d.ts.map +1 -0
  50. package/dist/mcp/tools/contracts.js +61 -0
  51. package/dist/mcp/tools/contracts.js.map +1 -0
  52. package/dist/mcp/tools/eval.d.ts +2 -0
  53. package/dist/mcp/tools/eval.d.ts.map +1 -0
  54. package/dist/mcp/tools/eval.js +157 -0
  55. package/dist/mcp/tools/eval.js.map +1 -0
  56. package/dist/mcp/tools/index.d.ts +20 -0
  57. package/dist/mcp/tools/index.d.ts.map +1 -0
  58. package/dist/mcp/tools/index.js +47 -0
  59. package/dist/mcp/tools/index.js.map +1 -0
  60. package/dist/mcp/tools/init.d.ts +2 -0
  61. package/dist/mcp/tools/init.d.ts.map +1 -0
  62. package/dist/mcp/tools/init.js +121 -0
  63. package/dist/mcp/tools/init.js.map +1 -0
  64. package/dist/mcp/tools/plan.d.ts +2 -0
  65. package/dist/mcp/tools/plan.d.ts.map +1 -0
  66. package/dist/mcp/tools/plan.js +97 -0
  67. package/dist/mcp/tools/plan.js.map +1 -0
  68. package/dist/mcp/tools/principles.d.ts +2 -0
  69. package/dist/mcp/tools/principles.d.ts.map +1 -0
  70. package/dist/mcp/tools/principles.js +66 -0
  71. package/dist/mcp/tools/principles.js.map +1 -0
  72. package/dist/mcp/tools/registry.d.ts +45 -0
  73. package/dist/mcp/tools/registry.d.ts.map +1 -0
  74. package/dist/mcp/tools/registry.js +23 -0
  75. package/dist/mcp/tools/registry.js.map +1 -0
  76. package/dist/mcp/tools/run.d.ts +2 -0
  77. package/dist/mcp/tools/run.d.ts.map +1 -0
  78. package/dist/mcp/tools/run.js +66 -0
  79. package/dist/mcp/tools/run.js.map +1 -0
  80. package/dist/mcp/tools/spec.d.ts +2 -0
  81. package/dist/mcp/tools/spec.d.ts.map +1 -0
  82. package/dist/mcp/tools/spec.js +32 -0
  83. package/dist/mcp/tools/spec.js.map +1 -0
  84. package/dist/mcp/tools/sprint.d.ts +2 -0
  85. package/dist/mcp/tools/sprint.d.ts.map +1 -0
  86. package/dist/mcp/tools/sprint.js +243 -0
  87. package/dist/mcp/tools/sprint.js.map +1 -0
  88. package/dist/mcp/tools/status.d.ts +2 -0
  89. package/dist/mcp/tools/status.d.ts.map +1 -0
  90. package/dist/mcp/tools/status.js +76 -0
  91. package/dist/mcp/tools/status.js.map +1 -0
  92. package/dist/orchestrator/agentic-loop.d.ts +7 -6
  93. package/dist/orchestrator/agentic-loop.d.ts.map +1 -1
  94. package/dist/orchestrator/agentic-loop.js +33 -40
  95. package/dist/orchestrator/agentic-loop.js.map +1 -1
  96. package/dist/orchestrator/context-handoff.d.ts +20 -20
  97. package/dist/orchestrator/evaluator-agent.d.ts.map +1 -1
  98. package/dist/orchestrator/evaluator-agent.js +2 -2
  99. package/dist/orchestrator/evaluator-agent.js.map +1 -1
  100. package/dist/orchestrator/generator-agent.d.ts.map +1 -1
  101. package/dist/orchestrator/generator-agent.js +2 -2
  102. package/dist/orchestrator/generator-agent.js.map +1 -1
  103. package/dist/orchestrator/model-resolver.d.ts +35 -4
  104. package/dist/orchestrator/model-resolver.d.ts.map +1 -1
  105. package/dist/orchestrator/model-resolver.js +68 -15
  106. package/dist/orchestrator/model-resolver.js.map +1 -1
  107. package/dist/orchestrator/planner-agent.d.ts.map +1 -1
  108. package/dist/orchestrator/planner-agent.js +2 -2
  109. package/dist/orchestrator/planner-agent.js.map +1 -1
  110. package/dist/orchestrator/tools/index.d.ts +3 -4
  111. package/dist/orchestrator/tools/index.d.ts.map +1 -1
  112. package/dist/orchestrator/tools/index.js.map +1 -1
  113. package/dist/orchestrator/tools/schemas.d.ts +11 -12
  114. package/dist/orchestrator/tools/schemas.d.ts.map +1 -1
  115. package/dist/orchestrator/tools/schemas.js +3 -2
  116. package/dist/orchestrator/tools/schemas.js.map +1 -1
  117. package/dist/providers/anthropic.d.ts +15 -0
  118. package/dist/providers/anthropic.d.ts.map +1 -0
  119. package/dist/providers/anthropic.js +133 -0
  120. package/dist/providers/anthropic.js.map +1 -0
  121. package/dist/providers/factory.d.ts +37 -0
  122. package/dist/providers/factory.d.ts.map +1 -0
  123. package/dist/providers/factory.js +119 -0
  124. package/dist/providers/factory.js.map +1 -0
  125. package/dist/providers/google.d.ts +39 -0
  126. package/dist/providers/google.d.ts.map +1 -0
  127. package/dist/providers/google.js +195 -0
  128. package/dist/providers/google.js.map +1 -0
  129. package/dist/providers/index.d.ts +7 -0
  130. package/dist/providers/index.d.ts.map +1 -0
  131. package/dist/providers/index.js +6 -0
  132. package/dist/providers/index.js.map +1 -0
  133. package/dist/providers/openai-compat.d.ts +39 -0
  134. package/dist/providers/openai-compat.d.ts.map +1 -0
  135. package/dist/providers/openai-compat.js +42 -0
  136. package/dist/providers/openai-compat.js.map +1 -0
  137. package/dist/providers/openai.d.ts +41 -0
  138. package/dist/providers/openai.d.ts.map +1 -0
  139. package/dist/providers/openai.js +205 -0
  140. package/dist/providers/openai.js.map +1 -0
  141. package/dist/providers/types.d.ts +144 -0
  142. package/dist/providers/types.d.ts.map +1 -0
  143. package/dist/providers/types.js +8 -0
  144. package/dist/providers/types.js.map +1 -0
  145. package/package.json +21 -3
@@ -0,0 +1,61 @@
1
+ // ── bober_contracts tool ──────────────────────────────────────────────
2
+ //
3
+ // No args -> list all contracts with id, feature, status, dependsOn.
4
+ // With { contractId } -> return the full contract JSON.
5
+ import { cwd } from "node:process";
6
+ import { listContracts, loadContract } from "../../state/index.js";
7
+ import { registerTool } from "./registry.js";
8
+ // ── Registration ─────────────────────────────────────────────────────
9
+ export function registerContractsTool() {
10
+ registerTool({
11
+ name: "bober_contracts",
12
+ description: "List all sprint contracts or read a specific contract. " +
13
+ "Without arguments returns a summary list of all contracts (id, feature, status, dependsOn). " +
14
+ "With contractId returns the full contract JSON including success criteria and evaluator feedback.",
15
+ inputSchema: {
16
+ type: "object",
17
+ properties: {
18
+ contractId: {
19
+ type: "string",
20
+ description: "Contract ID to read. Omit to list all contracts.",
21
+ },
22
+ },
23
+ additionalProperties: false,
24
+ },
25
+ handler: async (args) => {
26
+ const projectRoot = cwd();
27
+ const contractId = typeof args.contractId === "string" && args.contractId.trim()
28
+ ? args.contractId.trim()
29
+ : undefined;
30
+ // Return full contract when contractId is provided
31
+ if (contractId !== undefined) {
32
+ try {
33
+ const contract = await loadContract(projectRoot, contractId);
34
+ return JSON.stringify(contract, null, 2);
35
+ }
36
+ catch (err) {
37
+ return JSON.stringify({
38
+ error: `Contract "${contractId}" not found.`,
39
+ details: err instanceof Error ? err.message : String(err),
40
+ }, null, 2);
41
+ }
42
+ }
43
+ // List mode
44
+ const contracts = await listContracts(projectRoot);
45
+ if (contracts.length === 0) {
46
+ return JSON.stringify({
47
+ contracts: [],
48
+ message: "No contracts found. Run bober_plan first to generate sprint contracts.",
49
+ }, null, 2);
50
+ }
51
+ const summary = contracts.map((c) => ({
52
+ id: c.id,
53
+ feature: c.feature,
54
+ status: c.status,
55
+ dependsOn: c.dependsOn,
56
+ }));
57
+ return JSON.stringify({ contracts: summary }, null, 2);
58
+ },
59
+ });
60
+ }
61
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../../src/mcp/tools/contracts.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,qEAAqE;AACrE,wDAAwD;AAExD,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,wEAAwE;AAExE,MAAM,UAAU,qBAAqB;IACnC,YAAY,CAAC;QACX,IAAI,EAAE,iBAAiB;QACvB,WAAW,EACT,yDAAyD;YACzD,8FAA8F;YAC9F,mGAAmG;QACrG,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,WAAW,EACT,kDAAkD;iBACrD;aACF;YACD,oBAAoB,EAAE,KAAK;SAC5B;QACD,OAAO,EAAE,KAAK,EAAE,IAA6B,EAAmB,EAAE;YAChE,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC;YAC1B,MAAM,UAAU,GACd,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;gBAC3D,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;gBACxB,CAAC,CAAC,SAAS,CAAC;YAEhB,mDAAmD;YACnD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;gBAC7B,IAAI,CAAC;oBACH,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;oBAC7D,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;gBAC3C,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,IAAI,CAAC,SAAS,CACnB;wBACE,KAAK,EAAE,aAAa,UAAU,cAAc;wBAC5C,OAAO,EACL,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;qBACnD,EACD,IAAI,EACJ,CAAC,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,YAAY;YACZ,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;YACnD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC3B,OAAO,IAAI,CAAC,SAAS,CACnB;oBACE,SAAS,EAAE,EAAE;oBACb,OAAO,EACL,wEAAwE;iBAC3E,EACD,IAAI,EACJ,CAAC,CACF,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACpC,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,SAAS,EAAE,CAAC,CAAC,SAAS;aACvB,CAAC,CAAC,CAAC;YAEJ,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACzD,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function registerEvalTool(): void;
2
+ //# sourceMappingURL=eval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/eval.ts"],"names":[],"mappings":"AAwBA,wBAAgB,gBAAgB,IAAI,IAAI,CAuKvC"}
@@ -0,0 +1,157 @@
1
+ // ── bober_eval tool ──────────────────────────────────────────────────
2
+ //
3
+ // Runs the evaluator agent against a specific sprint or the most
4
+ // recent in-progress sprint.
5
+ // Accepts { sprintId?: string }. Returns a JSON eval result summary.
6
+ import { cwd } from "node:process";
7
+ import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
8
+ import { configExists, loadConfig } from "../../config/loader.js";
9
+ import { createHandoff } from "../../orchestrator/context-handoff.js";
10
+ import { runEvaluatorAgent } from "../../orchestrator/evaluator-agent.js";
11
+ import { ensureBoberDir, listContracts, loadLatestSpec, } from "../../state/index.js";
12
+ import { getCurrentBranch, getChangedFiles } from "../../utils/git.js";
13
+ import { registerTool } from "./registry.js";
14
+ // ── Registration ─────────────────────────────────────────────────────
15
+ export function registerEvalTool() {
16
+ registerTool({
17
+ name: "bober_eval",
18
+ description: "Run the Bober evaluator agent against a sprint. " +
19
+ "If sprintId is omitted the most recent in-progress, evaluating, or " +
20
+ "needs-rework sprint is targeted (falls back to the last contract). " +
21
+ "Returns a JSON object with pass/fail, score, per-criterion details, " +
22
+ "and actionable feedback.",
23
+ inputSchema: {
24
+ type: "object",
25
+ properties: {
26
+ sprintId: {
27
+ type: "string",
28
+ description: "ID of the sprint contract to evaluate. Omit to target the most " +
29
+ "recent active sprint.",
30
+ },
31
+ },
32
+ additionalProperties: false,
33
+ },
34
+ handler: async (args) => {
35
+ const sprintId = typeof args.sprintId === "string" && args.sprintId.trim()
36
+ ? args.sprintId.trim()
37
+ : undefined;
38
+ const projectRoot = cwd();
39
+ const hasConfig = await configExists(projectRoot);
40
+ if (!hasConfig) {
41
+ throw new McpError(ErrorCode.InvalidRequest, "No bober.config.json found. Run bober_init first.");
42
+ }
43
+ let config;
44
+ try {
45
+ config = await loadConfig(projectRoot);
46
+ }
47
+ catch (err) {
48
+ return JSON.stringify({
49
+ error: `Failed to load config: ${err instanceof Error ? err.message : String(err)}`,
50
+ });
51
+ }
52
+ await ensureBoberDir(projectRoot);
53
+ const spec = await loadLatestSpec(projectRoot);
54
+ if (!spec) {
55
+ return JSON.stringify({
56
+ error: "No plan found. Run bober_plan first.",
57
+ });
58
+ }
59
+ const contracts = await listContracts(projectRoot);
60
+ if (contracts.length === 0) {
61
+ return JSON.stringify({
62
+ error: "No sprint contracts found. Run bober_plan first.",
63
+ });
64
+ }
65
+ // Resolve target contract
66
+ let targetContract;
67
+ if (sprintId) {
68
+ targetContract = contracts.find((c) => c.id === sprintId);
69
+ if (!targetContract) {
70
+ return JSON.stringify({
71
+ error: `Sprint "${sprintId}" not found.`,
72
+ available: contracts.map((c) => c.id),
73
+ });
74
+ }
75
+ }
76
+ else {
77
+ targetContract = contracts.find((c) => c.status === "in-progress" ||
78
+ c.status === "evaluating" ||
79
+ c.status === "needs-rework");
80
+ if (!targetContract) {
81
+ // Fall back to the last contract
82
+ targetContract = contracts[contracts.length - 1];
83
+ }
84
+ }
85
+ process.stderr.write(`[bober_eval] Evaluating: ${targetContract.feature} (${targetContract.id})\n`);
86
+ // Build project context
87
+ let currentBranch;
88
+ try {
89
+ currentBranch = await getCurrentBranch(projectRoot);
90
+ }
91
+ catch {
92
+ currentBranch = "unknown";
93
+ }
94
+ const projectContext = {
95
+ name: config.project.name,
96
+ type: config.project.mode,
97
+ techStack: spec.techStack,
98
+ entryPoints: [],
99
+ currentBranch,
100
+ };
101
+ // Get changed files
102
+ let changedFiles;
103
+ try {
104
+ changedFiles = await getChangedFiles(projectRoot);
105
+ }
106
+ catch {
107
+ changedFiles = [];
108
+ }
109
+ const completedContracts = contracts.filter((c) => c.status === "passed");
110
+ const handoff = createHandoff({
111
+ from: "generator",
112
+ to: "evaluator",
113
+ projectContext,
114
+ spec,
115
+ currentContract: targetContract,
116
+ sprintHistory: completedContracts,
117
+ instructions: `Evaluate sprint: ${targetContract.feature}`,
118
+ changedFiles,
119
+ });
120
+ try {
121
+ const evaluation = await runEvaluatorAgent(handoff, projectRoot, config);
122
+ return JSON.stringify({
123
+ contractId: targetContract.id,
124
+ feature: targetContract.feature,
125
+ passed: evaluation.passed,
126
+ score: evaluation.score,
127
+ summary: evaluation.summary,
128
+ feedback: evaluation.results
129
+ .filter((r) => !r.passed && r.feedback)
130
+ .map((r) => ({ evaluator: r.evaluator, feedback: r.feedback })),
131
+ results: evaluation.results.map((r) => ({
132
+ evaluator: r.evaluator,
133
+ passed: r.passed,
134
+ score: r.score,
135
+ summary: r.summary,
136
+ failedCriteria: r.details
137
+ .filter((d) => !d.passed)
138
+ .map((d) => ({
139
+ message: d.message,
140
+ severity: d.severity,
141
+ ...(d.file ? { file: d.file, line: d.line } : {}),
142
+ })),
143
+ })),
144
+ timestamp: evaluation.timestamp,
145
+ }, null, 2);
146
+ }
147
+ catch (err) {
148
+ return JSON.stringify({
149
+ error: `Evaluation failed: ${err instanceof Error ? err.message : String(err)}`,
150
+ contractId: targetContract.id,
151
+ feature: targetContract.feature,
152
+ });
153
+ }
154
+ },
155
+ });
156
+ }
157
+ //# sourceMappingURL=eval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eval.js","sourceRoot":"","sources":["../../../src/mcp/tools/eval.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Registers all built-in agent-bober MCP tools into the global registry.
3
+ * Call this once before starting the MCP server.
4
+ *
5
+ * Registered tools (10 total):
6
+ * 1. bober_init – Initialise a project
7
+ * 2. bober_plan – Generate a sprint plan
8
+ * 3. bober_sprint – Execute the next sprint cycle
9
+ * 4. bober_eval – Evaluate a sprint
10
+ * 5. bober_run – Start the full pipeline asynchronously
11
+ * 6. bober_status – Poll pipeline status
12
+ * 7. bober_contracts – List/read sprint contracts
13
+ * 8. bober_spec – Read the latest plan spec
14
+ * 9. bober_principles – Read/write .bober/principles.md
15
+ * 10. bober_config – Read/update bober.config.json
16
+ */
17
+ export declare function registerAllTools(): void;
18
+ export { registerTool, getAllTools, getTool } from "./registry.js";
19
+ export type { BoberToolDefinition, JsonSchemaObject, JsonSchemaProperty, } from "./registry.js";
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/index.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAgBvC;AAED,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACnE,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,47 @@
1
+ // ── Tool Registration ───────────────────────────────────────────────
2
+ //
3
+ // This file is the central place where all MCP tools are registered.
4
+ // Import each tool module's register function here and call it once.
5
+ import { registerInitTool } from "./init.js";
6
+ import { registerPlanTool } from "./plan.js";
7
+ import { registerSprintTool } from "./sprint.js";
8
+ import { registerEvalTool } from "./eval.js";
9
+ import { registerRunTool } from "./run.js";
10
+ import { registerStatusTool } from "./status.js";
11
+ import { registerContractsTool } from "./contracts.js";
12
+ import { registerSpecTool } from "./spec.js";
13
+ import { registerPrinciplesTool } from "./principles.js";
14
+ import { registerConfigTool } from "./config.js";
15
+ /**
16
+ * Registers all built-in agent-bober MCP tools into the global registry.
17
+ * Call this once before starting the MCP server.
18
+ *
19
+ * Registered tools (10 total):
20
+ * 1. bober_init – Initialise a project
21
+ * 2. bober_plan – Generate a sprint plan
22
+ * 3. bober_sprint – Execute the next sprint cycle
23
+ * 4. bober_eval – Evaluate a sprint
24
+ * 5. bober_run – Start the full pipeline asynchronously
25
+ * 6. bober_status – Poll pipeline status
26
+ * 7. bober_contracts – List/read sprint contracts
27
+ * 8. bober_spec – Read the latest plan spec
28
+ * 9. bober_principles – Read/write .bober/principles.md
29
+ * 10. bober_config – Read/update bober.config.json
30
+ */
31
+ export function registerAllTools() {
32
+ // ── Core workflow tools ─────────────────────────────────────────
33
+ registerInitTool();
34
+ registerPlanTool();
35
+ registerSprintTool();
36
+ registerEvalTool();
37
+ // ── Async pipeline tools ────────────────────────────────────────
38
+ registerRunTool();
39
+ registerStatusTool();
40
+ // ── Read / configuration tools ──────────────────────────────────
41
+ registerContractsTool();
42
+ registerSpecTool();
43
+ registerPrinciplesTool();
44
+ registerConfigTool();
45
+ }
46
+ export { registerTool, getAllTools, getTool } from "./registry.js";
47
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/mcp/tools/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,EAAE;AACF,qEAAqE;AACrE,qEAAqE;AAErE,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,gBAAgB;IAC9B,mEAAmE;IACnE,gBAAgB,EAAE,CAAC;IACnB,gBAAgB,EAAE,CAAC;IACnB,kBAAkB,EAAE,CAAC;IACrB,gBAAgB,EAAE,CAAC;IAEnB,mEAAmE;IACnE,eAAe,EAAE,CAAC;IAClB,kBAAkB,EAAE,CAAC;IAErB,mEAAmE;IACnE,qBAAqB,EAAE,CAAC;IACxB,gBAAgB,EAAE,CAAC;IACnB,sBAAsB,EAAE,CAAC;IACzB,kBAAkB,EAAE,CAAC;AACvB,CAAC;AAED,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function registerInitTool(): void;
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/init.ts"],"names":[],"mappings":"AAmBA,wBAAgB,gBAAgB,IAAI,IAAI,CAsIvC"}
@@ -0,0 +1,121 @@
1
+ // ── bober_init tool ──────────────────────────────────────────────────
2
+ //
3
+ // Creates bober.config.json and .bober/ directories in the current
4
+ // working directory. Accepts { preset?: string, provider?: string }.
5
+ // Returns a confirmation message.
6
+ import { writeFile } from "node:fs/promises";
7
+ import { join, basename } from "node:path";
8
+ import { cwd } from "node:process";
9
+ import { configExists } from "../../config/loader.js";
10
+ import { createDefaultConfig } from "../../config/schema.js";
11
+ import { getPresetNames } from "../../config/defaults.js";
12
+ import { ensureBoberDir } from "../../state/index.js";
13
+ import { registerTool } from "./registry.js";
14
+ // ── Registration ─────────────────────────────────────────────────────
15
+ export function registerInitTool() {
16
+ registerTool({
17
+ name: "bober_init",
18
+ description: "Initialise a Bober project in the current working directory. " +
19
+ "Creates bober.config.json and the .bober/ state directory. " +
20
+ "Accepts an optional preset (e.g. nextjs, react-vite, api-node) and " +
21
+ "an optional provider (anthropic, openai, google, openai-compat). " +
22
+ "If a config already exists this will overwrite it.",
23
+ inputSchema: {
24
+ type: "object",
25
+ properties: {
26
+ preset: {
27
+ type: "string",
28
+ description: "Optional project preset. One of: nextjs, react-vite, api-node, " +
29
+ "python-api, solidity, anchor. Leave blank for a generic config.",
30
+ },
31
+ provider: {
32
+ type: "string",
33
+ description: "AI provider to use: anthropic (default), openai, google, openai-compat.",
34
+ default: "anthropic",
35
+ },
36
+ mode: {
37
+ type: "string",
38
+ description: "Project mode: greenfield (default) or brownfield.",
39
+ default: "greenfield",
40
+ },
41
+ projectName: {
42
+ type: "string",
43
+ description: "Project name. Defaults to the name of the current directory.",
44
+ },
45
+ },
46
+ additionalProperties: false,
47
+ },
48
+ handler: async (args) => {
49
+ const projectRoot = cwd();
50
+ const projectName = typeof args.projectName === "string" && args.projectName.trim()
51
+ ? args.projectName.trim()
52
+ : basename(projectRoot);
53
+ const rawPreset = typeof args.preset === "string" && args.preset.trim()
54
+ ? args.preset.trim()
55
+ : undefined;
56
+ const provider = typeof args.provider === "string" && args.provider.trim()
57
+ ? args.provider.trim()
58
+ : "anthropic";
59
+ const rawMode = typeof args.mode === "string" && args.mode.trim()
60
+ ? args.mode.trim()
61
+ : "greenfield";
62
+ const mode = rawMode === "brownfield" ? "brownfield" : "greenfield";
63
+ // Validate preset if provided
64
+ if (rawPreset) {
65
+ const knownPresets = getPresetNames();
66
+ if (!knownPresets.includes(rawPreset)) {
67
+ return JSON.stringify({
68
+ error: `Unknown preset "${rawPreset}".`,
69
+ availablePresets: knownPresets,
70
+ });
71
+ }
72
+ }
73
+ // Warn if already initialised (but proceed — tool contract says overwrite)
74
+ const alreadyExists = await configExists(projectRoot);
75
+ if (alreadyExists) {
76
+ process.stderr.write(`[bober_init] Overwriting existing bober.config.json in ${projectRoot}\n`);
77
+ }
78
+ // Build config
79
+ const config = createDefaultConfig(projectName, mode, rawPreset, {
80
+ planner: {
81
+ maxClarifications: 5,
82
+ model: "opus",
83
+ provider,
84
+ },
85
+ generator: {
86
+ model: "sonnet",
87
+ maxTurnsPerSprint: 50,
88
+ autoCommit: true,
89
+ branchPattern: "bober/{feature-name}",
90
+ provider,
91
+ },
92
+ evaluator: {
93
+ model: "sonnet",
94
+ strategies: [],
95
+ maxIterations: 3,
96
+ provider,
97
+ },
98
+ });
99
+ // Write bober.config.json
100
+ const configPath = join(projectRoot, "bober.config.json");
101
+ await writeFile(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
102
+ // Create .bober/ directory structure
103
+ await ensureBoberDir(projectRoot);
104
+ process.stderr.write(`[bober_init] Initialised project "${projectName}" in ${projectRoot}\n`);
105
+ return JSON.stringify({
106
+ status: "initialised",
107
+ projectName,
108
+ mode,
109
+ preset: rawPreset ?? null,
110
+ provider,
111
+ configPath,
112
+ boberDir: join(projectRoot, ".bober"),
113
+ message: alreadyExists
114
+ ? "Existing configuration was overwritten."
115
+ : "Project successfully initialised. Run bober_plan to create your first plan.",
116
+ nextStep: "Run bober_plan with a task description to generate a sprint plan.",
117
+ }, null, 2);
118
+ },
119
+ });
120
+ }
121
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/mcp/tools/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function registerPlanTool(): void;
2
+ //# sourceMappingURL=plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/plan.ts"],"names":[],"mappings":"AAkBA,wBAAgB,gBAAgB,IAAI,IAAI,CAiGvC"}
@@ -0,0 +1,97 @@
1
+ // ── bober_plan tool ─────────────────────────────────────────────────
2
+ //
3
+ // Accepts { task: string }, calls the planner agent, and returns a
4
+ // JSON summary of the produced PlanSpec.
5
+ import { cwd } from "node:process";
6
+ import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
7
+ import { configExists, loadConfig } from "../../config/loader.js";
8
+ import { createContract } from "../../contracts/sprint-contract.js";
9
+ import { runPlanner } from "../../orchestrator/planner-agent.js";
10
+ import { ensureBoberDir, saveContract } from "../../state/index.js";
11
+ import { registerTool } from "./registry.js";
12
+ // ── Registration ─────────────────────────────────────────────────────
13
+ export function registerPlanTool() {
14
+ registerTool({
15
+ name: "bober_plan",
16
+ description: "Run the Bober planner agent. Accepts a task/feature description and " +
17
+ "produces a PlanSpec with a sprint breakdown saved to .bober/specs/. " +
18
+ "Returns a JSON summary with the plan title, description, and sprint list.",
19
+ inputSchema: {
20
+ type: "object",
21
+ properties: {
22
+ task: {
23
+ type: "string",
24
+ description: "Feature or project description to plan.",
25
+ },
26
+ },
27
+ required: ["task"],
28
+ additionalProperties: false,
29
+ },
30
+ handler: async (args) => {
31
+ const task = String(args.task ?? "").trim();
32
+ if (!task) {
33
+ return JSON.stringify({ error: "task is required and must be a non-empty string." });
34
+ }
35
+ const projectRoot = cwd();
36
+ // Check config exists before attempting to load
37
+ const hasConfig = await configExists(projectRoot);
38
+ if (!hasConfig) {
39
+ throw new McpError(ErrorCode.InvalidRequest, "No bober.config.json found. Run bober_init first.");
40
+ }
41
+ let config;
42
+ try {
43
+ config = await loadConfig(projectRoot);
44
+ }
45
+ catch (err) {
46
+ return JSON.stringify({
47
+ error: `Failed to load config: ${err instanceof Error ? err.message : String(err)}`,
48
+ projectRoot,
49
+ });
50
+ }
51
+ await ensureBoberDir(projectRoot);
52
+ try {
53
+ const spec = await runPlanner(task, projectRoot, config);
54
+ // Generate sprint contracts from features (same as pipeline.ts)
55
+ const contracts = [];
56
+ for (const feature of spec.features) {
57
+ const contract = createContract(feature.title, feature.description, feature.acceptanceCriteria.map((ac, idx) => ({
58
+ id: `${feature.id}-criterion-${idx + 1}`,
59
+ description: ac,
60
+ verificationMethod: "agent-evaluation",
61
+ })));
62
+ contracts.push(contract);
63
+ await saveContract(projectRoot, contract);
64
+ }
65
+ const summary = {
66
+ id: spec.id,
67
+ title: spec.title,
68
+ description: spec.description,
69
+ projectType: spec.projectType,
70
+ techStack: spec.techStack,
71
+ sprintCount: spec.features.length,
72
+ sprints: spec.features.map((f, idx) => ({
73
+ id: f.id,
74
+ contractId: contracts[idx]?.id,
75
+ feature: f.title,
76
+ description: f.description,
77
+ priority: f.priority,
78
+ estimatedSprints: f.estimatedSprints,
79
+ criteriaCount: f.acceptanceCriteria.length,
80
+ status: "proposed",
81
+ })),
82
+ contractIds: contracts.map((c) => c.id),
83
+ nonFunctional: spec.nonFunctional,
84
+ constraints: spec.constraints,
85
+ savedTo: `.bober/specs/${spec.id}.json`,
86
+ };
87
+ return JSON.stringify(summary, null, 2);
88
+ }
89
+ catch (err) {
90
+ return JSON.stringify({
91
+ error: `Planner failed: ${err instanceof Error ? err.message : String(err)}`,
92
+ });
93
+ }
94
+ },
95
+ });
96
+ }
97
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/mcp/tools/plan.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,EAAE;AACF,mEAAmE;AACnE,yCAAyC;AAEzC,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AAEzE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,wEAAwE;AAExE,MAAM,UAAU,gBAAgB;IAC9B,YAAY,CAAC;QACX,IAAI,EAAE,YAAY;QAClB,WAAW,EACT,sEAAsE;YACtE,sEAAsE;YACtE,2EAA2E;QAC7E,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,yCAAyC;iBACvD;aACF;YACD,QAAQ,EAAE,CAAC,MAAM,CAAC;YAClB,oBAAoB,EAAE,KAAK;SAC5B;QACD,OAAO,EAAE,KAAK,EAAE,IAA6B,EAAmB,EAAE;YAChE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,kDAAkD,EAAE,CAAC,CAAC;YACvF,CAAC;YAED,MAAM,WAAW,GAAG,GAAG,EAAE,CAAC;YAE1B,gDAAgD;YAChD,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;YAClD,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,cAAc,EACxB,mDAAmD,CACpD,CAAC;YACJ,CAAC;YAED,IAAI,MAAM,CAAC;YACX,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,CAAC;YACzC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,IAAI,CAAC,SAAS,CAAC;oBACpB,KAAK,EAAE,0BAA0B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;oBACnF,WAAW;iBACZ,CAAC,CAAC;YACL,CAAC;YAED,MAAM,cAAc,CAAC,WAAW,CAAC,CAAC;YAElC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;gBAEzD,gEAAgE;gBAChE,MAAM,SAAS,GAAqB,EAAE,CAAC;gBACvC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACpC,MAAM,QAAQ,GAAG,cAAc,CAC7B,OAAO,CAAC,KAAK,EACb,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;wBAC3C,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,cAAc,GAAG,GAAG,CAAC,EAAE;wBACxC,WAAW,EAAE,EAAE;wBACf,kBAAkB,EAAE,kBAAkB;qBACvC,CAAC,CAAC,CACJ,CAAC;oBACF,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBACzB,MAAM,YAAY,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;gBAC5C,CAAC;gBAED,MAAM,OAAO,GAAG;oBACd,EAAE,EAAE,IAAI,CAAC,EAAE;oBACX,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,SAAS,EAAE,IAAI,CAAC,SAAS;oBACzB,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM;oBACjC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;wBACtC,EAAE,EAAE,CAAC,CAAC,EAAE;wBACR,UAAU,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE;wBAC9B,OAAO,EAAE,CAAC,CAAC,KAAK;wBAChB,WAAW,EAAE,CAAC,CAAC,WAAW;wBAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ;wBACpB,gBAAgB,EAAE,CAAC,CAAC,gBAAgB;wBACpC,aAAa,EAAE,CAAC,CAAC,kBAAkB,CAAC,MAAM;wBAC1C,MAAM,EAAE,UAAU;qBACnB,CAAC,CAAC;oBACH,WAAW,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACvC,aAAa,EAAE,IAAI,CAAC,aAAa;oBACjC,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,OAAO,EAAE,gBAAgB,IAAI,CAAC,EAAE,OAAO;iBACxC,CAAC;gBAEF,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC1C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,IAAI,CAAC,SAAS,CAAC;oBACpB,KAAK,EAAE,mBAAmB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;iBAC7E,CAAC,CAAC;YACL,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function registerPrinciplesTool(): void;
2
+ //# sourceMappingURL=principles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principles.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/principles.ts"],"names":[],"mappings":"AAsBA,wBAAgB,sBAAsB,IAAI,IAAI,CAwE7C"}
@@ -0,0 +1,66 @@
1
+ // ── bober_principles tool ─────────────────────────────────────────────
2
+ //
3
+ // No args -> read .bober/principles.md and return content.
4
+ // With { content } -> write/update .bober/principles.md.
5
+ import { readFile, writeFile } from "node:fs/promises";
6
+ import { join } from "node:path";
7
+ import { cwd } from "node:process";
8
+ import { ensureBoberDir } from "../../state/index.js";
9
+ import { registerTool } from "./registry.js";
10
+ // ── Constants ─────────────────────────────────────────────────────────
11
+ const PRINCIPLES_FILENAME = "principles.md";
12
+ function principlesPath(projectRoot) {
13
+ return join(projectRoot, ".bober", PRINCIPLES_FILENAME);
14
+ }
15
+ // ── Registration ─────────────────────────────────────────────────────
16
+ export function registerPrinciplesTool() {
17
+ registerTool({
18
+ name: "bober_principles",
19
+ description: "Read or write the project principles file (.bober/principles.md). " +
20
+ "Without arguments reads the current principles. " +
21
+ "With content writes/replaces the principles file. " +
22
+ "Principles are injected into every generator and evaluator agent prompt.",
23
+ inputSchema: {
24
+ type: "object",
25
+ properties: {
26
+ content: {
27
+ type: "string",
28
+ description: "Principles content to write. Omit to read current principles.",
29
+ },
30
+ },
31
+ additionalProperties: false,
32
+ },
33
+ handler: async (args) => {
34
+ const projectRoot = cwd();
35
+ const filePath = principlesPath(projectRoot);
36
+ const newContent = typeof args.content === "string" ? args.content : undefined;
37
+ // Write mode
38
+ if (newContent !== undefined) {
39
+ await ensureBoberDir(projectRoot);
40
+ await writeFile(filePath, newContent, "utf-8");
41
+ process.stderr.write(`[bober_principles] Wrote ${newContent.length} characters to ${filePath}\n`);
42
+ return JSON.stringify({
43
+ status: "updated",
44
+ path: filePath,
45
+ characters: newContent.length,
46
+ message: "Principles file updated. These will be injected into all future agent prompts.",
47
+ }, null, 2);
48
+ }
49
+ // Read mode
50
+ try {
51
+ const content = await readFile(filePath, "utf-8");
52
+ return JSON.stringify({
53
+ path: filePath,
54
+ content,
55
+ }, null, 2);
56
+ }
57
+ catch {
58
+ return JSON.stringify({
59
+ content: null,
60
+ message: "No principles file. Use bober_principles with content to create one.",
61
+ }, null, 2);
62
+ }
63
+ },
64
+ });
65
+ }
66
+ //# sourceMappingURL=principles.js.map