opencode-swarm-plugin 0.44.0 → 0.44.1

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 (205) hide show
  1. package/bin/swarm.serve.test.ts +6 -4
  2. package/bin/swarm.ts +16 -10
  3. package/dist/compaction-prompt-scoring.js +139 -0
  4. package/dist/eval-capture.js +12811 -0
  5. package/dist/hive.d.ts.map +1 -1
  6. package/dist/index.js +7644 -62599
  7. package/dist/plugin.js +23766 -78721
  8. package/dist/swarm-orchestrate.d.ts.map +1 -1
  9. package/dist/swarm-prompts.d.ts.map +1 -1
  10. package/dist/swarm-review.d.ts.map +1 -1
  11. package/package.json +17 -5
  12. package/.changeset/swarm-insights-data-layer.md +0 -63
  13. package/.hive/analysis/eval-failure-analysis-2025-12-25.md +0 -331
  14. package/.hive/analysis/session-data-quality-audit.md +0 -320
  15. package/.hive/eval-results.json +0 -483
  16. package/.hive/issues.jsonl +0 -138
  17. package/.hive/memories.jsonl +0 -729
  18. package/.opencode/eval-history.jsonl +0 -327
  19. package/.turbo/turbo-build.log +0 -9
  20. package/CHANGELOG.md +0 -2286
  21. package/SCORER-ANALYSIS.md +0 -598
  22. package/docs/analysis/subagent-coordination-patterns.md +0 -902
  23. package/docs/analysis-socratic-planner-pattern.md +0 -504
  24. package/docs/planning/ADR-001-monorepo-structure.md +0 -171
  25. package/docs/planning/ADR-002-package-extraction.md +0 -393
  26. package/docs/planning/ADR-003-performance-improvements.md +0 -451
  27. package/docs/planning/ADR-004-message-queue-features.md +0 -187
  28. package/docs/planning/ADR-005-devtools-observability.md +0 -202
  29. package/docs/planning/ADR-007-swarm-enhancements-worktree-review.md +0 -168
  30. package/docs/planning/ADR-008-worker-handoff-protocol.md +0 -293
  31. package/docs/planning/ADR-009-oh-my-opencode-patterns.md +0 -353
  32. package/docs/planning/ADR-010-cass-inhousing.md +0 -1215
  33. package/docs/planning/ROADMAP.md +0 -368
  34. package/docs/semantic-memory-cli-syntax.md +0 -123
  35. package/docs/swarm-mail-architecture.md +0 -1147
  36. package/docs/testing/context-recovery-test.md +0 -470
  37. package/evals/ARCHITECTURE.md +0 -1189
  38. package/evals/README.md +0 -768
  39. package/evals/compaction-prompt.eval.ts +0 -149
  40. package/evals/compaction-resumption.eval.ts +0 -289
  41. package/evals/coordinator-behavior.eval.ts +0 -307
  42. package/evals/coordinator-session.eval.ts +0 -154
  43. package/evals/evalite.config.ts.bak +0 -15
  44. package/evals/example.eval.ts +0 -31
  45. package/evals/fixtures/cass-baseline.ts +0 -217
  46. package/evals/fixtures/compaction-cases.ts +0 -350
  47. package/evals/fixtures/compaction-prompt-cases.ts +0 -311
  48. package/evals/fixtures/coordinator-sessions.ts +0 -328
  49. package/evals/fixtures/decomposition-cases.ts +0 -105
  50. package/evals/lib/compaction-loader.test.ts +0 -248
  51. package/evals/lib/compaction-loader.ts +0 -320
  52. package/evals/lib/data-loader.evalite-test.ts +0 -289
  53. package/evals/lib/data-loader.test.ts +0 -345
  54. package/evals/lib/data-loader.ts +0 -281
  55. package/evals/lib/llm.ts +0 -115
  56. package/evals/scorers/compaction-prompt-scorers.ts +0 -145
  57. package/evals/scorers/compaction-scorers.ts +0 -305
  58. package/evals/scorers/coordinator-discipline.evalite-test.ts +0 -539
  59. package/evals/scorers/coordinator-discipline.ts +0 -325
  60. package/evals/scorers/index.test.ts +0 -146
  61. package/evals/scorers/index.ts +0 -328
  62. package/evals/scorers/outcome-scorers.evalite-test.ts +0 -27
  63. package/evals/scorers/outcome-scorers.ts +0 -349
  64. package/evals/swarm-decomposition.eval.ts +0 -121
  65. package/examples/commands/swarm.md +0 -745
  66. package/examples/plugin-wrapper-template.ts +0 -2515
  67. package/examples/skills/hive-workflow/SKILL.md +0 -212
  68. package/examples/skills/skill-creator/SKILL.md +0 -223
  69. package/examples/skills/swarm-coordination/SKILL.md +0 -292
  70. package/global-skills/cli-builder/SKILL.md +0 -344
  71. package/global-skills/cli-builder/references/advanced-patterns.md +0 -244
  72. package/global-skills/learning-systems/SKILL.md +0 -644
  73. package/global-skills/skill-creator/LICENSE.txt +0 -202
  74. package/global-skills/skill-creator/SKILL.md +0 -352
  75. package/global-skills/skill-creator/references/output-patterns.md +0 -82
  76. package/global-skills/skill-creator/references/workflows.md +0 -28
  77. package/global-skills/swarm-coordination/SKILL.md +0 -995
  78. package/global-skills/swarm-coordination/references/coordinator-patterns.md +0 -235
  79. package/global-skills/swarm-coordination/references/strategies.md +0 -138
  80. package/global-skills/system-design/SKILL.md +0 -213
  81. package/global-skills/testing-patterns/SKILL.md +0 -430
  82. package/global-skills/testing-patterns/references/dependency-breaking-catalog.md +0 -586
  83. package/opencode-swarm-plugin-0.30.7.tgz +0 -0
  84. package/opencode-swarm-plugin-0.31.0.tgz +0 -0
  85. package/scripts/cleanup-test-memories.ts +0 -346
  86. package/scripts/init-skill.ts +0 -222
  87. package/scripts/migrate-unknown-sessions.ts +0 -349
  88. package/scripts/validate-skill.ts +0 -204
  89. package/src/agent-mail.ts +0 -1724
  90. package/src/anti-patterns.test.ts +0 -1167
  91. package/src/anti-patterns.ts +0 -448
  92. package/src/compaction-capture.integration.test.ts +0 -257
  93. package/src/compaction-hook.test.ts +0 -838
  94. package/src/compaction-hook.ts +0 -1204
  95. package/src/compaction-observability.integration.test.ts +0 -139
  96. package/src/compaction-observability.test.ts +0 -187
  97. package/src/compaction-observability.ts +0 -324
  98. package/src/compaction-prompt-scorers.test.ts +0 -475
  99. package/src/compaction-prompt-scoring.ts +0 -300
  100. package/src/contributor-tools.test.ts +0 -133
  101. package/src/contributor-tools.ts +0 -201
  102. package/src/dashboard.test.ts +0 -611
  103. package/src/dashboard.ts +0 -462
  104. package/src/error-enrichment.test.ts +0 -403
  105. package/src/error-enrichment.ts +0 -219
  106. package/src/eval-capture.test.ts +0 -1015
  107. package/src/eval-capture.ts +0 -929
  108. package/src/eval-gates.test.ts +0 -306
  109. package/src/eval-gates.ts +0 -218
  110. package/src/eval-history.test.ts +0 -508
  111. package/src/eval-history.ts +0 -214
  112. package/src/eval-learning.test.ts +0 -378
  113. package/src/eval-learning.ts +0 -360
  114. package/src/eval-runner.test.ts +0 -223
  115. package/src/eval-runner.ts +0 -402
  116. package/src/export-tools.test.ts +0 -476
  117. package/src/export-tools.ts +0 -257
  118. package/src/hive.integration.test.ts +0 -2241
  119. package/src/hive.ts +0 -1628
  120. package/src/index.ts +0 -940
  121. package/src/learning.integration.test.ts +0 -1815
  122. package/src/learning.ts +0 -1079
  123. package/src/logger.test.ts +0 -189
  124. package/src/logger.ts +0 -135
  125. package/src/mandate-promotion.test.ts +0 -473
  126. package/src/mandate-promotion.ts +0 -239
  127. package/src/mandate-storage.integration.test.ts +0 -601
  128. package/src/mandate-storage.test.ts +0 -578
  129. package/src/mandate-storage.ts +0 -794
  130. package/src/mandates.ts +0 -540
  131. package/src/memory-tools.test.ts +0 -195
  132. package/src/memory-tools.ts +0 -344
  133. package/src/memory.integration.test.ts +0 -334
  134. package/src/memory.test.ts +0 -158
  135. package/src/memory.ts +0 -527
  136. package/src/model-selection.test.ts +0 -188
  137. package/src/model-selection.ts +0 -68
  138. package/src/observability-tools.test.ts +0 -359
  139. package/src/observability-tools.ts +0 -871
  140. package/src/output-guardrails.test.ts +0 -438
  141. package/src/output-guardrails.ts +0 -381
  142. package/src/pattern-maturity.test.ts +0 -1160
  143. package/src/pattern-maturity.ts +0 -525
  144. package/src/planning-guardrails.test.ts +0 -491
  145. package/src/planning-guardrails.ts +0 -438
  146. package/src/plugin.ts +0 -23
  147. package/src/post-compaction-tracker.test.ts +0 -251
  148. package/src/post-compaction-tracker.ts +0 -237
  149. package/src/query-tools.test.ts +0 -636
  150. package/src/query-tools.ts +0 -324
  151. package/src/rate-limiter.integration.test.ts +0 -466
  152. package/src/rate-limiter.ts +0 -774
  153. package/src/replay-tools.test.ts +0 -496
  154. package/src/replay-tools.ts +0 -240
  155. package/src/repo-crawl.integration.test.ts +0 -441
  156. package/src/repo-crawl.ts +0 -610
  157. package/src/schemas/cell-events.test.ts +0 -347
  158. package/src/schemas/cell-events.ts +0 -807
  159. package/src/schemas/cell.ts +0 -257
  160. package/src/schemas/evaluation.ts +0 -166
  161. package/src/schemas/index.test.ts +0 -199
  162. package/src/schemas/index.ts +0 -286
  163. package/src/schemas/mandate.ts +0 -232
  164. package/src/schemas/swarm-context.ts +0 -115
  165. package/src/schemas/task.ts +0 -161
  166. package/src/schemas/worker-handoff.test.ts +0 -302
  167. package/src/schemas/worker-handoff.ts +0 -131
  168. package/src/sessions/agent-discovery.test.ts +0 -137
  169. package/src/sessions/agent-discovery.ts +0 -112
  170. package/src/sessions/index.ts +0 -15
  171. package/src/skills.integration.test.ts +0 -1192
  172. package/src/skills.test.ts +0 -643
  173. package/src/skills.ts +0 -1549
  174. package/src/storage.integration.test.ts +0 -341
  175. package/src/storage.ts +0 -884
  176. package/src/structured.integration.test.ts +0 -817
  177. package/src/structured.test.ts +0 -1046
  178. package/src/structured.ts +0 -762
  179. package/src/swarm-decompose.test.ts +0 -188
  180. package/src/swarm-decompose.ts +0 -1302
  181. package/src/swarm-deferred.integration.test.ts +0 -157
  182. package/src/swarm-deferred.test.ts +0 -38
  183. package/src/swarm-insights.test.ts +0 -214
  184. package/src/swarm-insights.ts +0 -459
  185. package/src/swarm-mail.integration.test.ts +0 -970
  186. package/src/swarm-mail.ts +0 -739
  187. package/src/swarm-orchestrate.integration.test.ts +0 -282
  188. package/src/swarm-orchestrate.test.ts +0 -548
  189. package/src/swarm-orchestrate.ts +0 -3084
  190. package/src/swarm-prompts.test.ts +0 -1270
  191. package/src/swarm-prompts.ts +0 -2077
  192. package/src/swarm-research.integration.test.ts +0 -701
  193. package/src/swarm-research.test.ts +0 -698
  194. package/src/swarm-research.ts +0 -472
  195. package/src/swarm-review.integration.test.ts +0 -285
  196. package/src/swarm-review.test.ts +0 -879
  197. package/src/swarm-review.ts +0 -709
  198. package/src/swarm-strategies.ts +0 -407
  199. package/src/swarm-worktree.test.ts +0 -501
  200. package/src/swarm-worktree.ts +0 -575
  201. package/src/swarm.integration.test.ts +0 -2377
  202. package/src/swarm.ts +0 -38
  203. package/src/tool-adapter.integration.test.ts +0 -1221
  204. package/src/tool-availability.ts +0 -461
  205. package/tsconfig.json +0 -28
package/src/structured.ts DELETED
@@ -1,762 +0,0 @@
1
- /**
2
- * Structured Output Module - JSON extraction and schema validation
3
- *
4
- * Handles parsing agent responses that contain JSON, with multiple fallback
5
- * strategies for malformed or wrapped content.
6
- *
7
- * ## Usage
8
- * 1. `structured_extract_json` - Raw JSON extraction from text (no validation)
9
- * 2. `structured_validate` - Extract + validate against named schema
10
- * 3. `structured_parse_evaluation` - Typed parsing for agent self-evaluations
11
- * 4. `structured_parse_decomposition` - Typed parsing for task breakdowns
12
- * 5. `structured_parse_cell_tree` - Typed parsing for epic + subtasks
13
- *
14
- * @module structured
15
- */
16
- import { tool } from "@opencode-ai/plugin";
17
- import { z, type ZodSchema } from "zod";
18
- import {
19
- EvaluationSchema,
20
- TaskDecompositionSchema,
21
- CellTreeSchema,
22
- ValidationResultSchema,
23
- CriterionEvaluationSchema,
24
- type Evaluation,
25
- type TaskDecomposition,
26
- type CellTree,
27
- type ValidationResult,
28
- } from "./schemas";
29
-
30
- // ============================================================================
31
- // Error Types
32
- // ============================================================================
33
-
34
- /**
35
- * Structured validation error with formatted feedback
36
- *
37
- * Contains both raw Zod errors for programmatic access and
38
- * pre-formatted error bullets suitable for retry prompts.
39
- */
40
- export class StructuredValidationError extends Error {
41
- public readonly errorBullets: string[];
42
-
43
- constructor(
44
- message: string,
45
- public readonly zodError: z.ZodError | null,
46
- public readonly rawInput: string,
47
- public readonly extractionMethod?: string,
48
- ) {
49
- super(message);
50
- this.name = "StructuredValidationError";
51
- this.errorBullets = zodError ? formatZodErrors(zodError) : [message];
52
- }
53
-
54
- /**
55
- * Format errors as bullet list for retry prompts
56
- */
57
- toFeedback(): string {
58
- return this.errorBullets.map((e) => `- ${e}`).join("\n");
59
- }
60
- }
61
-
62
- /**
63
- * Error when JSON cannot be extracted from text
64
- */
65
- export class JsonExtractionError extends Error {
66
- constructor(
67
- message: string,
68
- public readonly rawInput: string,
69
- public readonly attemptedStrategies: string[],
70
- ) {
71
- super(message);
72
- this.name = "JsonExtractionError";
73
- }
74
- }
75
-
76
- // ============================================================================
77
- // Helper Functions
78
- // ============================================================================
79
-
80
- /**
81
- * Format Zod validation errors as readable bullet points
82
- *
83
- * @param error - Zod error from schema validation
84
- * @returns Array of error messages suitable for feedback
85
- */
86
- function formatZodErrors(error: z.ZodError): string[] {
87
- return error.issues.map((issue) => {
88
- const path = issue.path.length > 0 ? `${issue.path.join(".")}: ` : "";
89
- return `${path}${issue.message}`;
90
- });
91
- }
92
-
93
- /**
94
- * Schema registry for named schema lookups
95
- */
96
- const SCHEMA_REGISTRY: Record<string, ZodSchema> = {
97
- evaluation: EvaluationSchema,
98
- task_decomposition: TaskDecompositionSchema,
99
- cell_tree: CellTreeSchema,
100
- };
101
-
102
- /**
103
- * Get schema by name from registry
104
- */
105
- function getSchemaByName(name: string): ZodSchema {
106
- const schema = SCHEMA_REGISTRY[name];
107
- if (!schema) {
108
- throw new Error(
109
- `Unknown schema: ${name}. Available: ${Object.keys(SCHEMA_REGISTRY).join(", ")}`,
110
- );
111
- }
112
- return schema;
113
- }
114
-
115
- /**
116
- * Extract JSON from text using multiple strategies.
117
- *
118
- * Strategies tried in priority order:
119
- * 1. Direct parse - fastest, works for clean JSON
120
- * 2. JSON code block - common in markdown responses
121
- * 3. Generic code block - fallback for unlabeled blocks
122
- * 4. First brace match - finds outermost {...}
123
- * 5. Last brace match - handles trailing content
124
- * 6. Repair attempt - fixes common issues (quotes, trailing commas)
125
- *
126
- * @param text Raw text potentially containing JSON
127
- * @returns Parsed JSON object or null if all strategies fail
128
- */
129
- function extractJsonFromText(text: string): [unknown, string] {
130
- const trimmed = text.trim();
131
- const strategies: string[] = [];
132
-
133
- // Strategy 1: Direct parse (entire string is valid JSON)
134
- strategies.push("direct_parse");
135
- try {
136
- return [JSON.parse(trimmed), "direct_parse"];
137
- } catch {
138
- // Continue to other strategies
139
- }
140
-
141
- // Strategy 2: Extract from ```json code blocks
142
- strategies.push("json_code_block");
143
- const jsonBlockMatch = trimmed.match(/```json\s*([\s\S]*?)```/i);
144
- if (jsonBlockMatch) {
145
- try {
146
- return [JSON.parse(jsonBlockMatch[1].trim()), "json_code_block"];
147
- } catch {
148
- // Continue to other strategies
149
- }
150
- }
151
-
152
- // Strategy 3: Extract from any code block (```...```)
153
- strategies.push("any_code_block");
154
- const codeBlockMatch = trimmed.match(/```\s*([\s\S]*?)```/);
155
- if (codeBlockMatch) {
156
- try {
157
- return [JSON.parse(codeBlockMatch[1].trim()), "any_code_block"];
158
- } catch {
159
- // Continue to other strategies
160
- }
161
- }
162
-
163
- // Strategy 4: Find first balanced {...} object
164
- strategies.push("brace_match_object");
165
- const objectJson = findBalancedBraces(trimmed, "{", "}");
166
- if (objectJson) {
167
- try {
168
- return [JSON.parse(objectJson), "brace_match_object"];
169
- } catch {
170
- // Continue to other strategies
171
- }
172
- }
173
-
174
- // Strategy 5: Find first balanced [...] array
175
- strategies.push("brace_match_array");
176
- const arrayJson = findBalancedBraces(trimmed, "[", "]");
177
- if (arrayJson) {
178
- try {
179
- return [JSON.parse(arrayJson), "brace_match_array"];
180
- } catch {
181
- // Continue to other strategies
182
- }
183
- }
184
-
185
- // Strategy 6: Try to repair common JSON issues and parse
186
- strategies.push("repair_json");
187
- const repaired = attemptJsonRepair(trimmed);
188
- if (repaired !== trimmed) {
189
- try {
190
- return [JSON.parse(repaired), "repair_json"];
191
- } catch {
192
- // All strategies failed
193
- }
194
- }
195
-
196
- throw new JsonExtractionError(
197
- "Could not extract valid JSON from response",
198
- text,
199
- strategies,
200
- );
201
- }
202
-
203
- /** Maximum nesting depth before aborting (prevents stack overflow on malformed input) */
204
- const MAX_BRACE_DEPTH = 100;
205
-
206
- /**
207
- * Find a balanced pair of braces/brackets
208
- */
209
- function findBalancedBraces(
210
- text: string,
211
- open: string,
212
- close: string,
213
- ): string | null {
214
- const startIdx = text.indexOf(open);
215
- if (startIdx === -1) return null;
216
-
217
- let depth = 0;
218
- let inString = false;
219
- let escapeNext = false;
220
-
221
- for (let i = startIdx; i < text.length; i++) {
222
- const char = text[i];
223
-
224
- if (escapeNext) {
225
- escapeNext = false;
226
- continue;
227
- }
228
-
229
- if (char === "\\") {
230
- escapeNext = true;
231
- continue;
232
- }
233
-
234
- if (char === '"') {
235
- inString = !inString;
236
- continue;
237
- }
238
-
239
- if (inString) continue;
240
-
241
- if (char === open) {
242
- depth++;
243
- if (depth > MAX_BRACE_DEPTH) {
244
- return null; // Malformed input - too deeply nested
245
- }
246
- } else if (char === close) {
247
- depth--;
248
- if (depth < 0) {
249
- return null; // Malformed input - unbalanced braces
250
- }
251
- if (depth === 0) {
252
- return text.slice(startIdx, i + 1);
253
- }
254
- }
255
- }
256
-
257
- return null;
258
- }
259
-
260
- /**
261
- * Attempt to repair common JSON issues.
262
- *
263
- * This is a simple heuristic - won't work for all cases.
264
- *
265
- * **Known Limitations:**
266
- * - Single quotes in nested objects may not be handled correctly
267
- * - Escaped quotes in keys can confuse the regex
268
- * - Multiline strings are not detected
269
- * - Trailing commas in nested arrays may be missed
270
- *
271
- * @param text Potentially malformed JSON string
272
- * @returns Repaired JSON string (may still be invalid)
273
- */
274
- function attemptJsonRepair(text: string): string {
275
- let repaired = text;
276
-
277
- // Find JSON-like content first
278
- const match = repaired.match(/[\[{][\s\S]*[\]}]/);
279
- if (!match) return text;
280
-
281
- repaired = match[0];
282
-
283
- // Replace single quotes with double quotes (but not inside strings)
284
- // This is a simple heuristic - won't work for all cases
285
- repaired = repaired.replace(/(?<![\\])'([^']*)'(?=\s*:)/g, '"$1"');
286
-
287
- // Remove trailing commas before } or ]
288
- repaired = repaired.replace(/,(\s*[}\]])/g, "$1");
289
-
290
- // Replace literal newlines in strings with \n
291
- repaired = repaired.replace(
292
- /"([^"]*)\n([^"]*)"/g,
293
- (_, before, after) => `"${before}\\n${after}"`,
294
- );
295
-
296
- return repaired;
297
- }
298
-
299
- // ============================================================================
300
- // Validation Result Types
301
- // ============================================================================
302
-
303
- /** Maximum characters to show in raw input previews */
304
- const RAW_INPUT_PREVIEW_LENGTH = 200;
305
-
306
- /**
307
- * Result of a structured validation attempt
308
- */
309
- interface StructuredValidationResult<T = unknown> {
310
- success: boolean;
311
- data?: T;
312
- attempts: number;
313
- errors?: string[];
314
- extractionMethod?: string;
315
- }
316
-
317
- // ============================================================================
318
- // Tool Definitions
319
- // ============================================================================
320
-
321
- /**
322
- * Extract JSON from markdown/text response
323
- *
324
- * Tries multiple extraction strategies in order:
325
- * 1. Direct JSON parse
326
- * 2. ```json code blocks
327
- * 3. Any code blocks
328
- * 4. Brace matching for objects
329
- * 5. Bracket matching for arrays
330
- * 6. JSON repair attempts
331
- */
332
- export const structured_extract_json = tool({
333
- description:
334
- "Extract JSON from markdown/text response. Tries multiple strategies: direct parse, code blocks, brace matching, JSON repair.",
335
- args: {
336
- text: tool.schema.string().describe("Text containing JSON to extract"),
337
- },
338
- async execute(args, ctx) {
339
- try {
340
- const [parsed, method] = extractJsonFromText(args.text);
341
- return JSON.stringify(
342
- {
343
- success: true,
344
- data: parsed,
345
- extraction_method: method,
346
- },
347
- null,
348
- 2,
349
- );
350
- } catch (error) {
351
- if (error instanceof JsonExtractionError) {
352
- return JSON.stringify(
353
- {
354
- success: false,
355
- error: error.message,
356
- attempted_strategies: error.attemptedStrategies,
357
- raw_input_preview: args.text.slice(0, RAW_INPUT_PREVIEW_LENGTH),
358
- },
359
- null,
360
- 2,
361
- );
362
- }
363
- throw error;
364
- }
365
- },
366
- });
367
-
368
- /**
369
- * Validate agent response against a named schema
370
- *
371
- * Extracts JSON from the response using multiple strategies,
372
- * then validates against the specified schema.
373
- */
374
- export const structured_validate = tool({
375
- description:
376
- "Validate agent response against a schema. Extracts JSON and validates with Zod. Returns structured errors for retry feedback.",
377
- args: {
378
- response: tool.schema.string().describe("Agent response to validate"),
379
- schema_name: tool.schema
380
- .enum(["evaluation", "task_decomposition", "cell_tree"])
381
- .describe(
382
- "Schema to validate against: " +
383
- "evaluation = agent self-eval with criteria, " +
384
- "task_decomposition = swarm task breakdown, " +
385
- "cell_tree = epic with subtasks",
386
- ),
387
- max_retries: tool.schema
388
- .number()
389
- .min(1)
390
- .max(5)
391
- .optional()
392
- .describe("Max retries (for tracking - actual retry logic is external)"),
393
- },
394
- async execute(args, ctx) {
395
- const maxRetries = args.max_retries ?? 3;
396
- const result: ValidationResult = {
397
- success: false,
398
- attempts: 1,
399
- errors: [],
400
- };
401
-
402
- // Check for empty response before attempting extraction
403
- if (!args.response || args.response.trim().length === 0) {
404
- return JSON.stringify({
405
- valid: false,
406
- error: "Response is empty or contains only whitespace",
407
- raw_input: "(empty)",
408
- });
409
- }
410
-
411
- // Step 1: Extract JSON
412
- let extracted: unknown;
413
- let extractionMethod: string;
414
-
415
- try {
416
- [extracted, extractionMethod] = extractJsonFromText(args.response);
417
- result.extractionMethod = extractionMethod;
418
- } catch (error) {
419
- if (error instanceof JsonExtractionError) {
420
- result.errors = [
421
- `JSON extraction failed after trying: ${error.attemptedStrategies.join(", ")}`,
422
- `Input preview: ${args.response.slice(0, RAW_INPUT_PREVIEW_LENGTH)}...`,
423
- ];
424
- return JSON.stringify(result, null, 2);
425
- }
426
- throw error;
427
- }
428
-
429
- // Step 2: Validate against schema
430
- try {
431
- const schema = getSchemaByName(args.schema_name);
432
- const validated = schema.parse(extracted);
433
-
434
- result.success = true;
435
- result.data = validated;
436
- delete result.errors;
437
-
438
- return JSON.stringify(result, null, 2);
439
- } catch (error) {
440
- if (error instanceof z.ZodError) {
441
- const formatted = formatZodErrors(error);
442
- result.errors = formatted;
443
-
444
- // Add hint for retries
445
- if (result.attempts < maxRetries) {
446
- result.errors.push(
447
- `\nFix these issues and try again (attempt ${result.attempts}/${maxRetries})`,
448
- );
449
- }
450
-
451
- return JSON.stringify(result, null, 2);
452
- }
453
- throw error;
454
- }
455
- },
456
- });
457
-
458
- /**
459
- * Parse and validate evaluation response from an agent
460
- *
461
- * Specialized tool for parsing self-evaluations. Returns
462
- * the validated Evaluation or structured errors.
463
- */
464
- export const structured_parse_evaluation = tool({
465
- description:
466
- "Parse and validate evaluation response from an agent. Uses EvaluationSchema.",
467
- args: {
468
- response: tool.schema
469
- .string()
470
- .describe("Agent response containing evaluation"),
471
- },
472
- async execute(args, ctx) {
473
- try {
474
- const [extracted, method] = extractJsonFromText(args.response);
475
- const validated = EvaluationSchema.parse(extracted) as Evaluation;
476
-
477
- return JSON.stringify(
478
- {
479
- success: true,
480
- data: validated,
481
- extraction_method: method,
482
- summary: {
483
- passed: validated.passed,
484
- criteria_count: Object.keys(validated.criteria).length,
485
- failed_criteria: Object.entries(validated.criteria)
486
- .filter(([_, v]) => {
487
- const criterion = v as z.infer<
488
- typeof CriterionEvaluationSchema
489
- >;
490
- return !criterion.passed;
491
- })
492
- .map(([k]) => k),
493
- },
494
- },
495
- null,
496
- 2,
497
- );
498
- } catch (error) {
499
- if (error instanceof JsonExtractionError) {
500
- return JSON.stringify(
501
- {
502
- success: false,
503
- error: "Failed to extract JSON from response",
504
- details: error.message,
505
- attempted_strategies: error.attemptedStrategies,
506
- feedback: [
507
- "- Response must contain valid JSON",
508
- "- Use ```json code blocks for clarity",
509
- "- Ensure all braces and brackets are balanced",
510
- ].join("\n"),
511
- },
512
- null,
513
- 2,
514
- );
515
- }
516
-
517
- if (error instanceof z.ZodError) {
518
- const bullets = formatZodErrors(error);
519
- return JSON.stringify(
520
- {
521
- success: false,
522
- error: "Evaluation does not match schema",
523
- validation_errors: bullets,
524
- feedback: bullets.map((e) => `- ${e}`).join("\n"),
525
- expected_shape: {
526
- passed: "boolean",
527
- criteria: "Record<string, { passed: boolean, feedback: string }>",
528
- overall_feedback: "string",
529
- retry_suggestion: "string | null",
530
- },
531
- },
532
- null,
533
- 2,
534
- );
535
- }
536
-
537
- throw error;
538
- }
539
- },
540
- });
541
-
542
- /**
543
- * Parse and validate task decomposition response
544
- *
545
- * Specialized tool for parsing decomposition results.
546
- * Validates the structure and returns file lists for reservations.
547
- */
548
- export const structured_parse_decomposition = tool({
549
- description:
550
- "Parse and validate task decomposition response. Uses TaskDecompositionSchema. Returns validated decomposition with file lists.",
551
- args: {
552
- response: tool.schema
553
- .string()
554
- .describe("Agent response containing decomposition"),
555
- },
556
- async execute(args, ctx) {
557
- try {
558
- const [extracted, method] = extractJsonFromText(args.response);
559
- const validated = TaskDecompositionSchema.parse(
560
- extracted,
561
- ) as TaskDecomposition;
562
-
563
- // Collect all files for reservation planning
564
- const allFiles = validated.subtasks.flatMap((s) => s.files);
565
- const uniqueFiles = [...new Set(allFiles)];
566
-
567
- return JSON.stringify(
568
- {
569
- success: true,
570
- data: validated,
571
- extraction_method: method,
572
- summary: {
573
- task:
574
- validated.task.slice(0, 50) +
575
- (validated.task.length > 50 ? "..." : ""),
576
- subtask_count: validated.subtasks.length,
577
- dependency_count: validated.dependencies?.length ?? 0,
578
- total_files: uniqueFiles.length,
579
- files: uniqueFiles,
580
- effort_breakdown: validated.subtasks.reduce(
581
- (acc, s) => {
582
- acc[s.estimated_effort] = (acc[s.estimated_effort] || 0) + 1;
583
- return acc;
584
- },
585
- {} as Record<string, number>,
586
- ),
587
- },
588
- },
589
- null,
590
- 2,
591
- );
592
- } catch (error) {
593
- if (error instanceof JsonExtractionError) {
594
- return JSON.stringify(
595
- {
596
- success: false,
597
- error: "Failed to extract JSON from response",
598
- details: error.message,
599
- attempted_strategies: error.attemptedStrategies,
600
- feedback: [
601
- "- Response must contain valid JSON",
602
- "- Use ```json code blocks for clarity",
603
- "- Ensure all braces and brackets are balanced",
604
- ].join("\n"),
605
- },
606
- null,
607
- 2,
608
- );
609
- }
610
-
611
- if (error instanceof z.ZodError) {
612
- const bullets = formatZodErrors(error);
613
- return JSON.stringify(
614
- {
615
- success: false,
616
- error: "Decomposition does not match schema",
617
- validation_errors: bullets,
618
- feedback: bullets.map((e) => `- ${e}`).join("\n"),
619
- expected_shape: {
620
- task: "string (original task)",
621
- reasoning: "string (optional)",
622
- subtasks: [
623
- {
624
- title: "string",
625
- description: "string",
626
- files: ["string array of file paths"],
627
- estimated_effort: "trivial | small | medium | large",
628
- risks: ["optional string array"],
629
- },
630
- ],
631
- dependencies: [
632
- {
633
- from: "number (subtask index)",
634
- to: "number (subtask index)",
635
- type: "blocks | requires | related",
636
- },
637
- ],
638
- },
639
- },
640
- null,
641
- 2,
642
- );
643
- }
644
-
645
- throw error;
646
- }
647
- },
648
- });
649
-
650
- /**
651
- * Parse and validate a bead tree (epic with subtasks)
652
- *
653
- * Validates the structure before creating cells.
654
- */
655
- export const structured_parse_cell_tree = tool({
656
- description:
657
- "Parse and validate bead tree response. Uses CellTreeSchema. Validates before creating epic with subtasks.",
658
- args: {
659
- response: tool.schema
660
- .string()
661
- .describe("Agent response containing bead tree"),
662
- },
663
- async execute(args, ctx) {
664
- try {
665
- const [extracted, method] = extractJsonFromText(args.response);
666
- const validated = CellTreeSchema.parse(extracted) as CellTree;
667
-
668
- // Collect all files for reservation planning
669
- const allFiles = validated.subtasks.flatMap((s) => s.files);
670
- const uniqueFiles = [...new Set(allFiles)];
671
-
672
- return JSON.stringify(
673
- {
674
- success: true,
675
- data: validated,
676
- extraction_method: method,
677
- summary: {
678
- epic_title: validated.epic.title,
679
- subtask_count: validated.subtasks.length,
680
- total_files: uniqueFiles.length,
681
- files: uniqueFiles,
682
- complexity_total: validated.subtasks.reduce(
683
- (sum, s) => sum + s.estimated_complexity,
684
- 0,
685
- ),
686
- },
687
- },
688
- null,
689
- 2,
690
- );
691
- } catch (error) {
692
- if (error instanceof JsonExtractionError) {
693
- return JSON.stringify(
694
- {
695
- success: false,
696
- error: "Failed to extract JSON from response",
697
- details: error.message,
698
- feedback: [
699
- "- Response must contain valid JSON",
700
- "- Use ```json code blocks for clarity",
701
- ].join("\n"),
702
- },
703
- null,
704
- 2,
705
- );
706
- }
707
-
708
- if (error instanceof z.ZodError) {
709
- const bullets = formatZodErrors(error);
710
- return JSON.stringify(
711
- {
712
- success: false,
713
- error: "Bead tree does not match schema",
714
- validation_errors: bullets,
715
- feedback: bullets.map((e) => `- ${e}`).join("\n"),
716
- expected_shape: {
717
- epic: { title: "string", description: "string (optional)" },
718
- subtasks: [
719
- {
720
- title: "string",
721
- description: "string (optional)",
722
- files: ["string array"],
723
- dependencies: ["number array of subtask indices"],
724
- estimated_complexity: "1-5",
725
- },
726
- ],
727
- },
728
- },
729
- null,
730
- 2,
731
- );
732
- }
733
-
734
- throw error;
735
- }
736
- },
737
- });
738
-
739
- // ============================================================================
740
- // Utility Exports (for use by other modules)
741
- // ============================================================================
742
-
743
- export { extractJsonFromText, formatZodErrors, getSchemaByName };
744
-
745
- // ============================================================================
746
- // Tool Exports
747
- // ============================================================================
748
-
749
- export const structuredTools = {
750
- structured_extract_json: structured_extract_json,
751
- structured_validate: structured_validate,
752
- structured_parse_evaluation: structured_parse_evaluation,
753
- structured_parse_decomposition: structured_parse_decomposition,
754
- structured_parse_cell_tree: structured_parse_cell_tree,
755
- };
756
-
757
- // ============================================================================
758
- // Backward Compatibility Aliases
759
- // ============================================================================
760
-
761
- /** @deprecated Use structured_parse_cell_tree instead */
762
- export const structured_parse_bead_tree = structured_parse_cell_tree;