@halfagiraf/clawx 0.2.8 → 0.2.10

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 (84) hide show
  1. package/README.md +63 -0
  2. package/dist/cli/forge.d.ts +4 -0
  3. package/dist/cli/forge.d.ts.map +1 -0
  4. package/dist/cli/forge.js +205 -0
  5. package/dist/cli/forge.js.map +1 -0
  6. package/dist/cli/main.js +3 -0
  7. package/dist/cli/main.js.map +1 -1
  8. package/dist/config/index.d.ts.map +1 -1
  9. package/dist/config/index.js +6 -0
  10. package/dist/config/index.js.map +1 -1
  11. package/dist/core/agent.d.ts.map +1 -1
  12. package/dist/core/agent.js +5 -2
  13. package/dist/core/agent.js.map +1 -1
  14. package/dist/forge/community.d.ts +25 -0
  15. package/dist/forge/community.d.ts.map +1 -0
  16. package/dist/forge/community.js +126 -0
  17. package/dist/forge/community.js.map +1 -0
  18. package/dist/forge/discover.d.ts +14 -0
  19. package/dist/forge/discover.d.ts.map +1 -0
  20. package/dist/forge/discover.js +134 -0
  21. package/dist/forge/discover.js.map +1 -0
  22. package/dist/forge/forge.test.d.ts +2 -0
  23. package/dist/forge/forge.test.d.ts.map +1 -0
  24. package/dist/forge/forge.test.js +202 -0
  25. package/dist/forge/forge.test.js.map +1 -0
  26. package/dist/forge/hardware.d.ts +8 -0
  27. package/dist/forge/hardware.d.ts.map +1 -0
  28. package/dist/forge/hardware.js +31 -0
  29. package/dist/forge/hardware.js.map +1 -0
  30. package/dist/forge/hf-client.d.ts +9 -0
  31. package/dist/forge/hf-client.d.ts.map +1 -0
  32. package/dist/forge/hf-client.js +101 -0
  33. package/dist/forge/hf-client.js.map +1 -0
  34. package/dist/forge/index.d.ts +13 -0
  35. package/dist/forge/index.d.ts.map +1 -0
  36. package/dist/forge/index.js +13 -0
  37. package/dist/forge/index.js.map +1 -0
  38. package/dist/forge/loader.d.ts +10 -0
  39. package/dist/forge/loader.d.ts.map +1 -0
  40. package/dist/forge/loader.js +385 -0
  41. package/dist/forge/loader.js.map +1 -0
  42. package/dist/forge/loader.test.d.ts +5 -0
  43. package/dist/forge/loader.test.d.ts.map +1 -0
  44. package/dist/forge/loader.test.js +15 -0
  45. package/dist/forge/loader.test.js.map +1 -0
  46. package/dist/forge/pipeline-builder.d.ts +9 -0
  47. package/dist/forge/pipeline-builder.d.ts.map +1 -0
  48. package/dist/forge/pipeline-builder.js +125 -0
  49. package/dist/forge/pipeline-builder.js.map +1 -0
  50. package/dist/forge/pipeline.d.ts +28 -0
  51. package/dist/forge/pipeline.d.ts.map +1 -0
  52. package/dist/forge/pipeline.js +206 -0
  53. package/dist/forge/pipeline.js.map +1 -0
  54. package/dist/forge/rank.d.ts +3 -0
  55. package/dist/forge/rank.d.ts.map +1 -0
  56. package/dist/forge/rank.js +138 -0
  57. package/dist/forge/rank.js.map +1 -0
  58. package/dist/forge/reasoner.d.ts +10 -0
  59. package/dist/forge/reasoner.d.ts.map +1 -0
  60. package/dist/forge/reasoner.js +312 -0
  61. package/dist/forge/reasoner.js.map +1 -0
  62. package/dist/forge/registry.d.ts +15 -0
  63. package/dist/forge/registry.d.ts.map +1 -0
  64. package/dist/forge/registry.js +149 -0
  65. package/dist/forge/registry.js.map +1 -0
  66. package/dist/forge/scaffold.d.ts +10 -0
  67. package/dist/forge/scaffold.d.ts.map +1 -0
  68. package/dist/forge/scaffold.js +412 -0
  69. package/dist/forge/scaffold.js.map +1 -0
  70. package/dist/forge/scaffolder.d.ts +9 -0
  71. package/dist/forge/scaffolder.d.ts.map +1 -0
  72. package/dist/forge/scaffolder.js +118 -0
  73. package/dist/forge/scaffolder.js.map +1 -0
  74. package/dist/forge/tester.d.ts +9 -0
  75. package/dist/forge/tester.d.ts.map +1 -0
  76. package/dist/forge/tester.js +103 -0
  77. package/dist/forge/tester.js.map +1 -0
  78. package/dist/forge/types.d.ts +54 -0
  79. package/dist/forge/types.d.ts.map +1 -0
  80. package/dist/forge/types.js +3 -0
  81. package/dist/forge/types.js.map +1 -0
  82. package/dist/types/index.d.ts +1 -0
  83. package/dist/types/index.d.ts.map +1 -1
  84. package/package.json +2 -1
@@ -0,0 +1,412 @@
1
+ // Forge v1: Scaffolding engine
2
+ import { join } from 'path';
3
+ import { mkdirSync, writeFileSync } from 'fs';
4
+ export function createScaffoldPlan(opportunity, options) {
5
+ const { outputType, outputName } = options;
6
+ if (outputType === 'tool') {
7
+ return createToolScaffoldPlan(opportunity, outputName);
8
+ }
9
+ else {
10
+ return createAppScaffoldPlan(opportunity, outputName);
11
+ }
12
+ }
13
+ function createToolScaffoldPlan(opportunity, toolName) {
14
+ const model = opportunity.primaryModel;
15
+ const dataset = opportunity.supportingDataset;
16
+ const files = [
17
+ {
18
+ path: 'README.md',
19
+ content: generateToolReadme(opportunity, toolName)
20
+ },
21
+ {
22
+ path: 'tool.json',
23
+ content: generateToolManifest(opportunity, toolName)
24
+ },
25
+ {
26
+ path: 'tool.ts',
27
+ content: generateToolCode(opportunity, toolName)
28
+ },
29
+ {
30
+ path: 'package.json',
31
+ content: generatePackageJson(toolName)
32
+ },
33
+ {
34
+ path: 'test-data/example.txt',
35
+ content: generateExampleData(opportunity)
36
+ }
37
+ ];
38
+ const integrationNotes = `To use this tool with Clawx:
39
+ 1. Build the tool: npm install && npm run build
40
+ 2. Copy the generated .js file to ~/.clawx/forge/tools/
41
+ 3. Restart Clawx or reload tools
42
+
43
+ The tool will appear as "${toolName}" in Clawx's available tools.`;
44
+ return {
45
+ opportunityId: opportunity.id,
46
+ outputType: 'tool',
47
+ outputName: toolName,
48
+ files,
49
+ integrationNotes
50
+ };
51
+ }
52
+ function createAppScaffoldPlan(opportunity, appName) {
53
+ const model = opportunity.primaryModel;
54
+ const dataset = opportunity.supportingDataset;
55
+ const files = [
56
+ {
57
+ path: 'README.md',
58
+ content: generateAppReadme(opportunity, appName)
59
+ },
60
+ {
61
+ path: 'app.py',
62
+ content: generatePythonApp(opportunity, appName)
63
+ },
64
+ {
65
+ path: 'requirements.txt',
66
+ content: generateRequirements(opportunity)
67
+ },
68
+ {
69
+ path: 'config.yaml',
70
+ content: generateConfig(opportunity)
71
+ },
72
+ {
73
+ path: 'examples/example_usage.py',
74
+ content: generateExampleUsage(opportunity)
75
+ }
76
+ ];
77
+ return {
78
+ opportunityId: opportunity.id,
79
+ outputType: 'app',
80
+ outputName: appName,
81
+ files
82
+ };
83
+ }
84
+ export function executeScaffoldPlan(plan, outputDir) {
85
+ console.log(`🏗️ Scaffolding ${plan.outputType}: ${plan.outputName}`);
86
+ console.log(`📁 Output directory: ${outputDir}`);
87
+ // Create output directory
88
+ mkdirSync(outputDir, { recursive: true });
89
+ // Create all files
90
+ for (const file of plan.files) {
91
+ const filePath = join(outputDir, file.path);
92
+ // Create subdirectories if needed
93
+ const dirPath = join(outputDir, file.path.split('/').slice(0, -1).join('/'));
94
+ if (dirPath !== outputDir) {
95
+ mkdirSync(dirPath, { recursive: true });
96
+ }
97
+ writeFileSync(filePath, file.content, 'utf8');
98
+ console.log(` 📄 Created: ${file.path}`);
99
+ }
100
+ // Show integration notes if tool
101
+ if (plan.integrationNotes) {
102
+ console.log('\n🔧 Integration notes:');
103
+ console.log(plan.integrationNotes);
104
+ }
105
+ console.log(`\n✅ Scaffolding complete!`);
106
+ console.log(`Next steps: cd ${outputDir} and follow the README`);
107
+ }
108
+ // Content generators
109
+ function generateToolReadme(opportunity, toolName) {
110
+ const model = opportunity.primaryModel;
111
+ const dataset = opportunity.supportingDataset;
112
+ return `# ${toolName}
113
+
114
+ ${opportunity.description}
115
+
116
+ ## Model
117
+ - **Name**: ${model.name}
118
+ - **Author**: ${model.author}
119
+ - **Task**: ${model.task || 'N/A'}
120
+ - **Modality**: ${model.modality || 'N/A'}
121
+ - **License**: ${model.license || 'N/A'}
122
+
123
+ ${dataset ? `## Dataset
124
+ - **Name**: ${dataset.name}
125
+ - **Author**: ${dataset.author}
126
+ - **Task**: ${dataset.task || 'N/A'}
127
+ ` : ''}
128
+
129
+ ## Setup
130
+ \`\`\`bash
131
+ npm install
132
+ npm run build
133
+ \`\`\`
134
+
135
+ ## Usage with Clawx
136
+ 1. Copy the generated \`tool.js\` to \`~/.clawx/forge/tools/\`
137
+ 2. Restart Clawx
138
+ 3. The tool will be available as "${toolName}"
139
+
140
+ ## Development
141
+ - Edit \`tool.ts\` to customize the implementation
142
+ - Update \`tool.json\` to modify the tool definition
143
+ - Add tests in \`test-data/\`
144
+
145
+ ## Notes
146
+ - This is a starter project generated by Clawx Forge
147
+ - You may need to install additional dependencies
148
+ - Consider hardware requirements: ${model.hardware?.gpu ? 'GPU recommended' : 'CPU only'}
149
+ `;
150
+ }
151
+ function generateToolManifest(opportunity, toolName) {
152
+ const model = opportunity.primaryModel;
153
+ return JSON.stringify({
154
+ name: toolName.toLowerCase().replace(/\s+/g, '_'),
155
+ label: toolName,
156
+ description: opportunity.description,
157
+ parameters: {
158
+ input: {
159
+ type: "string",
160
+ description: `Input ${model.modality || 'data'} to process`
161
+ }
162
+ },
163
+ implementation: {
164
+ type: "custom",
165
+ file: "./tool.js"
166
+ },
167
+ metadata: {
168
+ model: model.id,
169
+ task: model.task,
170
+ generatedBy: "clawx-forge",
171
+ generatedAt: new Date().toISOString()
172
+ }
173
+ }, null, 2);
174
+ }
175
+ function generateToolCode(opportunity, toolName) {
176
+ const model = opportunity.primaryModel;
177
+ return `// ${toolName} - Generated by Clawx Forge
178
+ // Model: ${model.id}
179
+ // Task: ${model.task || 'N/A'}
180
+
181
+ import { AgentTool } from '@mariozechner/pi-agent-core';
182
+
183
+ export function createTool(): AgentTool<any> {
184
+ return {
185
+ name: '${toolName.toLowerCase().replace(/\s+/g, '_')}',
186
+ label: '${toolName}',
187
+ description: \`${opportunity.description}\`,
188
+
189
+ parameters: {
190
+ type: 'object',
191
+ properties: {
192
+ input: {
193
+ type: 'string',
194
+ description: 'Input to process'
195
+ }
196
+ },
197
+ required: ['input']
198
+ },
199
+
200
+ async execute(toolCallId, args, context) {
201
+ const input = args.input;
202
+
203
+ // TODO: Implement actual model inference
204
+ // For now, return a simulated result
205
+
206
+ return {
207
+ toolCallId,
208
+ content: [{
209
+ type: 'text',
210
+ text: \`Processed input using ${model.name}\\n\\nInput: "\${input}"\\n\\nResult: Simulated output (replace with real inference)\`
211
+ }],
212
+ details: {
213
+ model: '${model.id}',
214
+ simulated: true,
215
+ note: 'Replace with actual model inference'
216
+ }
217
+ };
218
+ }
219
+ };
220
+ }
221
+ `;
222
+ }
223
+ function generatePackageJson(toolName) {
224
+ return JSON.stringify({
225
+ name: toolName.toLowerCase().replace(/\s+/g, '-'),
226
+ version: "0.1.0",
227
+ description: `Clawx tool: ${toolName}`,
228
+ main: "tool.js",
229
+ scripts: {
230
+ build: "tsc tool.ts --outDir . --module commonjs --target es2020",
231
+ test: "echo 'No tests yet'"
232
+ },
233
+ dependencies: {
234
+ "@mariozechner/pi-agent-core": "^0.1.0"
235
+ },
236
+ devDependencies: {
237
+ "typescript": "^5.0.0"
238
+ }
239
+ }, null, 2);
240
+ }
241
+ function generateExampleData(opportunity) {
242
+ const model = opportunity.primaryModel;
243
+ if (model.modality === 'text') {
244
+ return "This is example text to classify or process.\nReplace with your own data.";
245
+ }
246
+ else if (model.modality === 'image') {
247
+ return "# Example image data would go here\n# Use actual image files for testing";
248
+ }
249
+ else {
250
+ return `Example data for ${model.modality || 'unknown'} modality`;
251
+ }
252
+ }
253
+ function generateAppReadme(opportunity, appName) {
254
+ const model = opportunity.primaryModel;
255
+ const dataset = opportunity.supportingDataset;
256
+ return `# ${appName}
257
+
258
+ ${opportunity.description}
259
+
260
+ ## Quick Start
261
+ \`\`\`bash
262
+ # Install dependencies
263
+ pip install -r requirements.txt
264
+
265
+ # Run the app
266
+ python app.py
267
+ \`\`\`
268
+
269
+ ## Model Details
270
+ - **Name**: ${model.name}
271
+ - **Author**: ${model.author}
272
+ - **Task**: ${model.task || 'N/A'}
273
+ - **Downloads**: ${model.downloads.toLocaleString()}
274
+
275
+ ${dataset ? `## Dataset
276
+ - **Name**: ${dataset.name}
277
+ - **Downloads**: ${dataset.downloads.toLocaleString()}
278
+ ` : ''}
279
+
280
+ ## Configuration
281
+ Edit \`config.yaml\` to customize:
282
+ - Model parameters
283
+ - Input/output settings
284
+ - Hardware preferences
285
+
286
+ ## Examples
287
+ See \`examples/\` directory for usage examples.
288
+
289
+ ## Hardware Requirements
290
+ ${model.hardware?.gpu ? '⚠️ GPU recommended for best performance' : '✅ CPU should work fine'}
291
+ ${model.hardware?.memory === 'high' ? '⚠️ High memory required (>8GB RAM)' : ''}
292
+
293
+ ## License
294
+ ${model.license ? `Model license: ${model.license}` : 'Check model license on Hugging Face Hub'}
295
+ `;
296
+ }
297
+ function generatePythonApp(opportunity, appName) {
298
+ const model = opportunity.primaryModel;
299
+ const modelTask = model.task || 'N/A';
300
+ return `#!/usr/bin/env python3
301
+ """
302
+ ${appName} - Generated by Clawx Forge
303
+ Model: ${model.id}
304
+ """
305
+
306
+ import yaml
307
+ import argparse
308
+ from pathlib import Path
309
+
310
+ def load_config():
311
+ """Load configuration from config.yaml"""
312
+ config_path = Path(__file__).parent / 'config.yaml'
313
+ with open(config_path, 'r') as f:
314
+ return yaml.safe_load(f)
315
+
316
+ def main():
317
+ """Main application entry point"""
318
+ parser = argparse.ArgumentParser(description='${opportunity.description}')
319
+ parser.add_argument('--input', type=str, help='Input to process')
320
+ parser.add_argument('--output', type=str, help='Output file path')
321
+ args = parser.parse_args()
322
+
323
+ config = load_config()
324
+
325
+ print(f"Starting ${appName}")
326
+ print(f"Model: ${model.id}")
327
+ print(f"Task: ${modelTask}")
328
+
329
+ if args.input:
330
+ print(f"Processing input: {args.input}")
331
+ # TODO: Add actual model inference here
332
+ result = f"Simulated result for: {args.input}"
333
+
334
+ if args.output:
335
+ with open(args.output, 'w') as f:
336
+ f.write(result)
337
+ print(f"Result saved to: {args.output}")
338
+ else:
339
+ print(f"Result: {result}")
340
+ else:
341
+ print("No input provided. Use --input <text> to process data.")
342
+ print("Example: python app.py --input 'Hello world'")
343
+
344
+ if __name__ == '__main__':
345
+ main()
346
+ `;
347
+ }
348
+ function generateRequirements(opportunity) {
349
+ const model = opportunity.primaryModel;
350
+ let requirements = [
351
+ "PyYAML>=6.0",
352
+ "argparse"
353
+ ];
354
+ // Add model-specific requirements
355
+ if (model.task === 'text-classification' || model.task === 'text-generation') {
356
+ requirements.push("transformers>=4.30.0");
357
+ requirements.push("torch>=2.0.0");
358
+ }
359
+ if (model.modality === 'image') {
360
+ requirements.push("Pillow>=9.0.0");
361
+ }
362
+ return requirements.join('\n');
363
+ }
364
+ function generateConfig(opportunity) {
365
+ const model = opportunity.primaryModel;
366
+ return `# ${opportunity.title}
367
+ # Generated by Clawx Forge
368
+
369
+ model:
370
+ id: "${model.id}"
371
+ name: "${model.name}"
372
+ task: "${model.task || 'N/A'}"
373
+
374
+ inference:
375
+ device: "auto" # auto, cpu, cuda
376
+ batch_size: 1
377
+ max_length: 512
378
+
379
+ output:
380
+ format: "text" # text, json, yaml
381
+ save_to_file: true
382
+
383
+ logging:
384
+ level: "INFO"
385
+ file: "app.log"
386
+ `;
387
+ }
388
+ function generateExampleUsage(opportunity) {
389
+ const model = opportunity.primaryModel;
390
+ return `# Example usage for ${opportunity.title}
391
+
392
+ import sys
393
+ sys.path.append('..')
394
+
395
+ from app import main
396
+
397
+ # Example 1: Basic usage
398
+ print("Example 1: Process text")
399
+ # python app.py --input "Your text here"
400
+
401
+ # Example 2: Save to file
402
+ print("Example 2: Save output to file")
403
+ # python app.py --input "Your text" --output result.txt
404
+
405
+ # Example 3: Batch processing (conceptual)
406
+ print("Example 3: Batch processing")
407
+ # for text in texts:
408
+ # result = process(text)
409
+ # print(result)
410
+ `;
411
+ }
412
+ //# sourceMappingURL=scaffold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/forge/scaffold.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Forge capability scaffolder.
3
+ *
4
+ * Builds discovered capabilities into working Clawx tools.
5
+ */
6
+ import type { ClawxConfig } from "../types/index.js";
7
+ import type { BuildOptions } from "./types.js";
8
+ export declare function buildCapability(config: ClawxConfig, capabilityId: string, options?: BuildOptions): Promise<void>;
9
+ //# sourceMappingURL=scaffolder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffolder.d.ts","sourceRoot":"","sources":["../../src/forge/scaffolder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAA4C,MAAM,YAAY,CAAC;AAKzF,wBAAsB,eAAe,CACnC,MAAM,EAAE,WAAW,EACnB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CAgEf"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Forge capability scaffolder.
3
+ *
4
+ * Builds discovered capabilities into working Clawx tools.
5
+ */
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ import { loadCapability, saveCapability, getForgeToolsDir } from "./registry.js";
9
+ import { testCapability } from "./tester.js";
10
+ import { log } from "../utils/logger.js";
11
+ export async function buildCapability(config, capabilityId, options = {}) {
12
+ console.log(`\n🔨 Building capability: ${capabilityId}\n`);
13
+ // Load the capability
14
+ const capability = await loadCapability(capabilityId);
15
+ if (!capability) {
16
+ console.error(` ❌ Capability not found: ${capabilityId}`);
17
+ process.exit(1);
18
+ }
19
+ if (capability.status === "built" && !options.force) {
20
+ console.log(` ℹ️ Capability already built. Use --force to rebuild.`);
21
+ return;
22
+ }
23
+ // Update status
24
+ capability.status = "building";
25
+ await saveCapability(capability);
26
+ try {
27
+ // Generate JSON tool definition
28
+ const toolDef = generateJsonToolDefinition(capability);
29
+ const toolPath = path.join(getForgeToolsDir(), `${capability.implementation.toolName}.json`);
30
+ // Check if tool already exists
31
+ if (fs.existsSync(toolPath) && !options.force) {
32
+ console.error(` ❌ Tool already exists: ${capability.implementation.toolName}`);
33
+ console.error(` Use --force to overwrite.`);
34
+ capability.status = "failed";
35
+ await saveCapability(capability);
36
+ process.exit(1);
37
+ }
38
+ // Create directory if needed
39
+ fs.mkdirSync(getForgeToolsDir(), { recursive: true });
40
+ // Write JSON tool definition
41
+ fs.writeFileSync(toolPath, JSON.stringify(toolDef, null, 2), "utf-8");
42
+ console.log(` ✅ Generated tool: ${toolPath}`);
43
+ // Update capability status
44
+ capability.status = "built";
45
+ capability.builtAt = new Date().toISOString();
46
+ await saveCapability(capability);
47
+ // Run tests
48
+ console.log(`\n🧪 Running tests...\n`);
49
+ const passed = await testCapability(config, capability);
50
+ if (!passed) {
51
+ console.error(` ❌ Tests failed`);
52
+ process.exit(1);
53
+ }
54
+ console.log(`\n✨ Capability built successfully!`);
55
+ console.log(`\n📋 Tool ready to use in Clawx sessions`);
56
+ console.log(` Tool name: ${capability.implementation.toolName}`);
57
+ console.log(` Example: ${capability.implementation.exampleUsage}`);
58
+ }
59
+ catch (error) {
60
+ log.error("Build failed:", error);
61
+ capability.status = "failed";
62
+ await saveCapability(capability);
63
+ throw error;
64
+ }
65
+ }
66
+ function generateJsonToolDefinition(capability) {
67
+ const toolName = capability.implementation.toolName;
68
+ // Determine implementation type based on capability
69
+ let implementationType = "simulated";
70
+ if (toolName.includes('classify'))
71
+ implementationType = "classification";
72
+ if (toolName.includes('generate'))
73
+ implementationType = "generation";
74
+ if (toolName.includes('summarize'))
75
+ implementationType = "summarization";
76
+ if (toolName.includes('qa'))
77
+ implementationType = "qa";
78
+ // Convert parameters to JSON schema format
79
+ const parameters = {};
80
+ for (const [key, type] of Object.entries(capability.implementation.parameters)) {
81
+ let paramType = "string";
82
+ if (type === "number")
83
+ paramType = "number";
84
+ if (type === "array")
85
+ paramType = "array";
86
+ if (type === "boolean")
87
+ paramType = "boolean";
88
+ parameters[key] = {
89
+ type: paramType,
90
+ description: key,
91
+ };
92
+ }
93
+ return {
94
+ name: toolName,
95
+ label: capability.name,
96
+ description: capability.description,
97
+ parameters,
98
+ implementation: {
99
+ type: implementationType,
100
+ models: capability.models.map(m => ({
101
+ id: m.id,
102
+ classificationType: m.classificationType,
103
+ supportedLabels: m.supportedLabels,
104
+ verified: m.verified
105
+ })),
106
+ config: {
107
+ simulated: true,
108
+ exampleOutput: `This is a simulated ${implementationType} tool. To make it real, implement actual model inference.`
109
+ }
110
+ },
111
+ metadata: {
112
+ capabilityId: capability.id,
113
+ builtAt: new Date().toISOString(),
114
+ version: "1.0.0"
115
+ }
116
+ };
117
+ }
118
+ //# sourceMappingURL=scaffolder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffolder.js","sourceRoot":"","sources":["../../src/forge/scaffolder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Forge capability tester.
3
+ *
4
+ * Tests built capabilities to ensure they work correctly.
5
+ */
6
+ import type { ClawxConfig } from "../types/index.js";
7
+ import type { DiscoveredCapability } from "./types.js";
8
+ export declare function testCapability(config: ClawxConfig, capability: DiscoveredCapability): Promise<boolean>;
9
+ //# sourceMappingURL=tester.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tester.d.ts","sourceRoot":"","sources":["../../src/forge/tester.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAIvD,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,oBAAoB,GAC/B,OAAO,CAAC,OAAO,CAAC,CAiDlB"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Forge capability tester.
3
+ *
4
+ * Tests built capabilities to ensure they work correctly.
5
+ */
6
+ import { saveCapability } from "./registry.js";
7
+ import { log } from "../utils/logger.js";
8
+ export async function testCapability(config, capability) {
9
+ console.log(`Testing: ${capability.name}`);
10
+ // Update status
11
+ capability.status = "tested";
12
+ try {
13
+ // For now, run simple validation tests
14
+ // In a real implementation, this would:
15
+ // 1. Load the generated tool
16
+ // 2. Execute it with sample inputs
17
+ // 3. Verify outputs
18
+ // 4. Test edge cases
19
+ const tests = [
20
+ validateToolStructure(capability),
21
+ validateParameters(capability),
22
+ // Add more tests as needed
23
+ ];
24
+ const allPassed = tests.every(test => test.passed);
25
+ capability.testResults = {
26
+ passed: allPassed,
27
+ details: tests.map(t => t.message).join('\n'),
28
+ timestamp: new Date().toISOString(),
29
+ };
30
+ await saveCapability(capability);
31
+ if (allPassed) {
32
+ console.log(` ✅ All tests passed`);
33
+ return true;
34
+ }
35
+ else {
36
+ console.log(` ❌ Some tests failed:`);
37
+ tests.filter(t => !t.passed).forEach(t => console.log(` - ${t.message}`));
38
+ return false;
39
+ }
40
+ }
41
+ catch (error) {
42
+ log.error("Test failed:", error);
43
+ capability.testResults = {
44
+ passed: false,
45
+ details: `Test error: ${error instanceof Error ? error.message : String(error)}`,
46
+ timestamp: new Date().toISOString(),
47
+ };
48
+ await saveCapability(capability);
49
+ return false;
50
+ }
51
+ }
52
+ function validateToolStructure(capability) {
53
+ const requiredFields = ['id', 'name', 'description', 'models', 'implementation'];
54
+ const missing = requiredFields.filter(field => !(field in capability));
55
+ if (missing.length > 0) {
56
+ return {
57
+ passed: false,
58
+ message: `Missing required fields: ${missing.join(', ')}`
59
+ };
60
+ }
61
+ if (!capability.implementation.toolName) {
62
+ return {
63
+ passed: false,
64
+ message: 'Implementation missing toolName'
65
+ };
66
+ }
67
+ return {
68
+ passed: true,
69
+ message: 'Tool structure valid'
70
+ };
71
+ }
72
+ function validateParameters(capability) {
73
+ const params = capability.implementation.parameters;
74
+ if (!params || typeof params !== 'object') {
75
+ return {
76
+ passed: false,
77
+ message: 'No parameters defined'
78
+ };
79
+ }
80
+ const paramCount = Object.keys(params).length;
81
+ if (paramCount === 0) {
82
+ return {
83
+ passed: false,
84
+ message: 'At least one parameter required'
85
+ };
86
+ }
87
+ // Check for valid parameter types
88
+ const validTypes = ['string', 'number', 'array', 'boolean', 'object'];
89
+ const invalidTypes = Object.entries(params)
90
+ .filter(([_, type]) => !validTypes.includes(type))
91
+ .map(([name]) => name);
92
+ if (invalidTypes.length > 0) {
93
+ return {
94
+ passed: false,
95
+ message: `Invalid parameter types: ${invalidTypes.join(', ')}. Valid types: ${validTypes.join(', ')}`
96
+ };
97
+ }
98
+ return {
99
+ passed: true,
100
+ message: `Parameters valid (${paramCount} parameters)`
101
+ };
102
+ }
103
+ //# sourceMappingURL=tester.js.map