@holoscript/framework 6.0.3 → 6.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/CHANGELOG.md +1 -2
  2. package/ROADMAP.md +68 -66
  3. package/dist/{InvisibleWallet-BB6tFvRA.d.cts → InvisibleWallet-EFiuaLn3.d.cts} +1 -1
  4. package/dist/{OrchestratorAgent-BvWgf9uw.d.cts → OrchestratorAgent-CrLDGNL6.d.cts} +1 -1
  5. package/dist/agents/index.cjs +11 -10
  6. package/dist/agents/index.d.cts +4 -16
  7. package/dist/ai/index.cjs +2 -2
  8. package/dist/behavior.cjs +10 -0
  9. package/dist/economy/index.cjs +4 -4
  10. package/dist/economy/index.d.cts +2 -2
  11. package/dist/index.cjs +33 -11
  12. package/dist/index.d.cts +3 -3
  13. package/dist/swarm/index.cjs +3 -0
  14. package/package.json +14 -9
  15. package/src/__tests__/bounty-marketplace.test.ts +53 -21
  16. package/src/__tests__/delegation.test.ts +1 -4
  17. package/src/__tests__/done-log-audit.test.ts +38 -46
  18. package/src/__tests__/framework.test.ts +172 -53
  19. package/src/__tests__/goal-synthesizer.test.ts +9 -6
  20. package/src/__tests__/presence.test.ts +1 -1
  21. package/src/__tests__/protocol-agent.test.ts +12 -11
  22. package/src/__tests__/revenue-splitter.test.ts +22 -15
  23. package/src/__tests__/scenario-driven-todo.test.ts +55 -35
  24. package/src/__tests__/self-improve.test.ts +28 -9
  25. package/src/__tests__/service-lifecycle.test.ts +9 -3
  26. package/src/__tests__/skill-router.test.ts +3 -3
  27. package/src/agents/CulturalMemory.ts +6 -6
  28. package/src/agents/DelegationTraceHooks.ts +560 -0
  29. package/src/agents/FederatedRegistryAdapter.ts +1 -1
  30. package/src/agents/NormEngine.ts +3 -8
  31. package/src/agents/OrchestratorAgent.ts +1 -1
  32. package/src/agents/TaskDelegationService.ts +5 -9
  33. package/src/agents/__tests__/AgentWalletRegistry.test.ts +5 -4
  34. package/src/agents/__tests__/CrossRealityHandoff.test.ts +9 -3
  35. package/src/agents/__tests__/DelegationTraceHooks.test.ts +390 -0
  36. package/src/agents/__tests__/TaskDelegationService.test.ts +4 -2
  37. package/src/agents/spatial-comms/Layer1RealTime.ts +36 -19
  38. package/src/agents/spatial-comms/Layer2A2A.ts +1 -3
  39. package/src/agents/spatial-comms/Layer3MCP.ts +13 -4
  40. package/src/agents/spatial-comms/ProtocolTypes.ts +5 -2
  41. package/src/agents/spatial-comms/examples/multi-agent-world-creation.ts +2 -2
  42. package/src/ai/HoloScriptGenerator.ts +2 -2
  43. package/src/ai/__tests__/PerceptionSystem.prod.test.ts +1 -1
  44. package/src/ai/__tests__/PerceptionSystem.test.ts +14 -14
  45. package/src/ai/__tests__/SteeringBehaviors.prod.test.ts +1 -1
  46. package/src/ai/index.ts +5 -1
  47. package/src/board/audit.ts +17 -6
  48. package/src/board/board-ops.ts +45 -15
  49. package/src/board/board-types.ts +94 -20
  50. package/src/delegation.ts +5 -3
  51. package/src/distributed-claimer.ts +13 -2
  52. package/src/economy/BountyManager.ts +40 -18
  53. package/src/economy/KnowledgeMarketplace.ts +27 -8
  54. package/src/economy/PaymentWebhookService.ts +0 -1
  55. package/src/economy/RevenueSplitter.ts +2 -4
  56. package/src/economy/UnifiedBudgetOptimizer.ts +8 -9
  57. package/src/economy/_core-stubs.ts +1 -1
  58. package/src/economy/x402-facilitator.ts +17 -8
  59. package/src/index.ts +16 -12
  60. package/src/knowledge/__tests__/knowledge-consolidator.test.ts +138 -89
  61. package/src/knowledge/__tests__/knowledge-store-vector.test.ts +59 -16
  62. package/src/knowledge/brain.ts +7 -7
  63. package/src/knowledge/consolidation.ts +16 -16
  64. package/src/knowledge/knowledge-consolidator.ts +60 -30
  65. package/src/knowledge/knowledge-store.ts +83 -45
  66. package/src/learning/ProceduralCompiler.ts +6 -1
  67. package/src/learning/learning/MemoryConsolidator.ts +102 -0
  68. package/src/learning/learning/MemoryScorer.ts +69 -0
  69. package/src/learning/learning/ProceduralCompiler.ts +45 -0
  70. package/src/learning/learning/SemanticClusterer.ts +66 -0
  71. package/src/llm/llm-adapter.ts +24 -10
  72. package/src/mesh/index.ts +37 -17
  73. package/src/protocol/goal-synthesizer.ts +24 -34
  74. package/src/protocol/implementations.ts +91 -22
  75. package/src/protocol/micro-phase-decomposer.ts +25 -17
  76. package/src/protocol/micro-step-decomposer.test.ts +104 -39
  77. package/src/protocol-agent.test.ts +17 -7
  78. package/src/protocol-agent.ts +45 -42
  79. package/src/self-improve/absorb-scanner.ts +9 -6
  80. package/src/self-improve/evolution-engine.ts +36 -18
  81. package/src/self-improve/framework-absorber.ts +21 -16
  82. package/src/self-improve/index.ts +2 -10
  83. package/src/self-improve/prompt-optimizer.ts +31 -19
  84. package/src/self-improve/test-generator.ts +16 -12
  85. package/src/skill-router.ts +7 -6
  86. package/src/swarm/messaging/GossipProtocol.ts +1 -1
  87. package/src/swarm/messaging/__tests__/BroadcastChannel.prod.test.ts +31 -9
  88. package/src/swarm/messaging/__tests__/GossipProtocol.prod.test.ts +21 -7
  89. package/src/swarm/messaging/__tests__/SwarmEventBus.prod.test.ts +24 -8
  90. package/src/swarm/messaging/__tests__/SwarmEventBus.test.ts +6 -2
  91. package/src/team.ts +277 -122
  92. package/src/training/scripts/generate-spatial-dataset.ts +1 -1
  93. package/src/training/training/LRScheduler.ts +377 -0
  94. package/src/training/training/QualityScoringPipeline.ts +139 -0
  95. package/src/training/training/SoftDedup.ts +461 -0
  96. package/src/training/training/SparsityMonitor.ts +685 -0
  97. package/src/training/training/SparsityMonitorTypes.ts +209 -0
  98. package/src/training/training/SpatialTrainingDataGenerator.ts +1526 -0
  99. package/src/training/training/SpatialTrainingDataTypes.ts +216 -0
  100. package/src/training/training/TrainingPipelineConfig.ts +215 -0
  101. package/src/training/training/__tests__/CorpusValidation.test.ts +87 -0
  102. package/src/training/training/__tests__/LRScheduler.test.ts +592 -0
  103. package/src/training/training/__tests__/SoftDedup.test.ts +415 -0
  104. package/src/training/training/__tests__/SparsityMonitor.test.ts +1623 -0
  105. package/src/training/training/__tests__/SpatialCorpusValidation.test.ts +72 -0
  106. package/src/training/training/__tests__/SpatialTrainingDataGenerator.test.ts +1244 -0
  107. package/src/training/training/__tests__/TrainingMonkeyIntegration.test.ts +897 -0
  108. package/src/training/training/__tests__/TrainingPipelineConfig.test.ts +202 -0
  109. package/src/training/training/__tests__/schema.test.ts +72 -0
  110. package/src/training/training/__tests__/training-constants.test.ts +106 -0
  111. package/src/training/training/__tests__/trait-mappings.test.ts +81 -0
  112. package/src/training/training/constants.ts +94 -0
  113. package/src/training/training/index.ts +17 -0
  114. package/src/training/training/schema.ts +147 -0
  115. package/src/training/training/scripts/generate-novel-use-cases-dataset.ts +272 -0
  116. package/src/training/training/scripts/generate-spatial-dataset.ts +521 -0
  117. package/src/training/training/trainingmonkey/TrainingMonkeyIntegration.ts +477 -0
  118. package/src/training/training/trainingmonkey/TrainingMonkeyTypes.ts +230 -0
  119. package/src/training/training/trainingmonkey/index.ts +26 -0
  120. package/src/training/training/trait-mappings.ts +157 -0
  121. package/src/types.ts +2 -7
  122. package/ALL-test-results.json +0 -1
  123. package/LICENSE +0 -21
  124. package/dist/AgentManifest-CB4xM-Ma.d.ts +0 -704
  125. package/dist/BehaviorTree-BrBFECv5.d.ts +0 -103
  126. package/dist/InvisibleWallet-rtRrBOA8.d.ts +0 -1732
  127. package/dist/OrchestratorAgent-Q_CbVTmO.d.ts +0 -798
  128. package/dist/agents/index.d.ts +0 -1788
  129. package/dist/agents/index.js +0 -4695
  130. package/dist/ai/index.d.ts +0 -1753
  131. package/dist/ai/index.js +0 -5244
  132. package/dist/behavior.d.ts +0 -130
  133. package/dist/behavior.js +0 -407
  134. package/dist/economy/index.d.ts +0 -747
  135. package/dist/economy/index.js +0 -3617
  136. package/dist/implementations-D9T3un9D.d.ts +0 -236
  137. package/dist/index.d.ts +0 -1729
  138. package/dist/index.js +0 -24277
  139. package/dist/learning/index.d.ts +0 -104
  140. package/dist/learning/index.js +0 -189
  141. package/dist/negotiation/index.d.ts +0 -610
  142. package/dist/negotiation/index.js +0 -931
  143. package/dist/skills/index.d.ts +0 -289
  144. package/dist/skills/index.js +0 -1079
  145. package/dist/swarm/index.d.ts +0 -2433
  146. package/dist/swarm/index.js +0 -5221
  147. package/dist/training/index.d.ts +0 -1734
  148. package/dist/training/index.js +0 -2687
  149. package/extract-failures.js +0 -10
  150. package/src/training/training/data/novel-use-cases.jsonl +0 -153
  151. package/src/training/training/data/spatial-reasoning-10k.jsonl +0 -9354
  152. package/src/types/core-stubs.d.ts +0 -113
  153. package/test-output.txt +0 -0
  154. package/test-result.json +0 -1
  155. package/tsc-errors.txt +0 -4
  156. package/tsc_output.txt +0 -0
  157. package/typescript-errors-2.txt +0 -0
  158. package/typescript-errors.txt +0 -22
  159. package/vitest-log-utf8.txt +0 -268
  160. package/vitest-log.txt +0 -0
@@ -1,1079 +0,0 @@
1
- // src/skills/skill-md-bridge.ts
2
- function parseHsplus(source) {
3
- const errors = [];
4
- const warnings = [];
5
- const sourceComments = extractLeadingComments(source);
6
- const compositionMatch = source.match(/composition\s+"([^"]+)"\s*\{/);
7
- if (!compositionMatch) {
8
- errors.push('No composition declaration found. Expected: composition "name" { ... }');
9
- return { success: false, errors, warnings };
10
- }
11
- const compositionName = compositionMatch[1];
12
- const description = extractDescription(sourceComments);
13
- const versionMatch = source.match(/@version\s+([\d.]+)/);
14
- const version = versionMatch ? versionMatch[1] : "1.0.0";
15
- const traits = extractTraits(source);
16
- const state = extractStateVars(source);
17
- const steps = extractBTSteps(source);
18
- const tests = extractTests(source);
19
- const environment = extractEnvironment(source);
20
- const objects = extractObjectNames(source);
21
- const economyTrait = traits.find((t) => t.name === "economy");
22
- const spendLimit = economyTrait?.config?.default_spend_limit;
23
- const inputSchema = extractSchemaFields(source, "input_schema");
24
- const outputSchema = extractSchemaFields(source, "output_schema");
25
- const tagsMatch = source.match(/@tags\s+(.+)/);
26
- const tags = tagsMatch ? tagsMatch[1].split(",").map((t) => t.trim()).filter(Boolean) : void 0;
27
- const metadata = {
28
- name: compositionName,
29
- description: description || `HoloClaw skill: ${compositionName}`,
30
- version,
31
- author: "HoloScript",
32
- holoCliVersion: "5.0.0",
33
- nodeVersion: "20",
34
- spendLimit,
35
- userInvocable: true,
36
- inputSchema: inputSchema.length > 0 ? inputSchema : void 0,
37
- outputSchema: outputSchema.length > 0 ? outputSchema : void 0,
38
- tags
39
- };
40
- return {
41
- success: true,
42
- data: {
43
- metadata,
44
- traits,
45
- state,
46
- steps,
47
- tests,
48
- environment: environment || void 0,
49
- objects: objects.length > 0 ? objects : void 0,
50
- sourceComments
51
- },
52
- errors,
53
- warnings
54
- };
55
- }
56
- function toSkillMd(skill) {
57
- const errors = [];
58
- const warnings = [];
59
- const lines = [];
60
- lines.push("---");
61
- lines.push(`name: ${skill.metadata.name}`);
62
- lines.push("description: >");
63
- const descWords = skill.metadata.description.split(/\s+/);
64
- let descLine = " ";
65
- for (const word of descWords) {
66
- if (descLine.length + word.length + 1 > 80) {
67
- lines.push(descLine);
68
- descLine = " " + word;
69
- } else {
70
- descLine += (descLine.trim().length > 0 ? " " : "") + word;
71
- }
72
- }
73
- if (descLine.trim().length > 0) lines.push(descLine);
74
- if (skill.metadata.version !== "1.0.0") {
75
- lines.push(`version: ${skill.metadata.version}`);
76
- }
77
- if (skill.metadata.author && skill.metadata.author !== "HoloScript") {
78
- lines.push(`author: ${skill.metadata.author}`);
79
- }
80
- if (skill.metadata.category) {
81
- lines.push(`category: ${skill.metadata.category}`);
82
- }
83
- if (skill.metadata.tags && skill.metadata.tags.length > 0) {
84
- lines.push(`tags: [${skill.metadata.tags.join(", ")}]`);
85
- }
86
- if (skill.metadata.homepage) {
87
- lines.push(`homepage: ${skill.metadata.homepage}`);
88
- }
89
- if (skill.metadata.license) {
90
- lines.push(`license: ${skill.metadata.license}`);
91
- }
92
- if (skill.metadata.repository) {
93
- lines.push(`repository: ${skill.metadata.repository}`);
94
- }
95
- if (skill.metadata.inputSchema && skill.metadata.inputSchema.length > 0) {
96
- lines.push("input_schema:");
97
- for (const field of skill.metadata.inputSchema) {
98
- lines.push(` - name: ${field.name}`);
99
- lines.push(` type: ${field.type}`);
100
- if (field.required !== void 0) lines.push(` required: ${field.required}`);
101
- lines.push(` description: ${field.description}`);
102
- if (field.default !== void 0) lines.push(` default: ${JSON.stringify(field.default)}`);
103
- }
104
- }
105
- if (skill.metadata.outputSchema && skill.metadata.outputSchema.length > 0) {
106
- lines.push("output_schema:");
107
- for (const field of skill.metadata.outputSchema) {
108
- lines.push(` - name: ${field.name}`);
109
- lines.push(` type: ${field.type}`);
110
- lines.push(` description: ${field.description}`);
111
- }
112
- }
113
- lines.push("---");
114
- lines.push("");
115
- const titleName = skill.metadata.name.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
116
- lines.push(`# ${titleName}`);
117
- lines.push("");
118
- lines.push(skill.metadata.description);
119
- lines.push("");
120
- lines.push("## Runtime Requirements");
121
- lines.push("");
122
- lines.push(`- **holoscript-cli** >= ${skill.metadata.holoCliVersion || "5.0.0"}`);
123
- lines.push(`- **Node.js** >= ${skill.metadata.nodeVersion || "20"}`);
124
- if (skill.metadata.spendLimit !== void 0) {
125
- lines.push(`- **Economy budget**: $${skill.metadata.spendLimit.toFixed(2)} per invocation`);
126
- }
127
- lines.push("");
128
- if (skill.traits.length > 0) {
129
- lines.push("## Traits");
130
- lines.push("");
131
- for (const trait of skill.traits) {
132
- const configStr = Object.keys(trait.config).length > 0 ? ` (${Object.entries(trait.config).map(([k, v]) => `${k}: ${JSON.stringify(v)}`).join(", ")})` : "";
133
- lines.push(`- \`@${trait.name}\`${configStr}`);
134
- }
135
- lines.push("");
136
- }
137
- if (skill.state.length > 0) {
138
- lines.push("## State Schema");
139
- lines.push("");
140
- lines.push("| Variable | Type | Default |");
141
- lines.push("|----------|------|---------|");
142
- for (const sv of skill.state) {
143
- lines.push(`| \`${sv.name}\` | ${sv.type} | \`${JSON.stringify(sv.defaultValue)}\` |`);
144
- }
145
- lines.push("");
146
- }
147
- if (skill.metadata.inputSchema && skill.metadata.inputSchema.length > 0) {
148
- lines.push("## Input Schema");
149
- lines.push("");
150
- lines.push("| Field | Type | Required | Description |");
151
- lines.push("|-------|------|----------|-------------|");
152
- for (const field of skill.metadata.inputSchema) {
153
- const req = field.required ? "yes" : "no";
154
- const defaultStr = field.default !== void 0 ? ` (default: \`${JSON.stringify(field.default)}\`)` : "";
155
- lines.push(
156
- `| \`${field.name}\` | ${field.type} | ${req} | ${field.description}${defaultStr} |`
157
- );
158
- }
159
- lines.push("");
160
- }
161
- if (skill.metadata.outputSchema && skill.metadata.outputSchema.length > 0) {
162
- lines.push("## Output Schema");
163
- lines.push("");
164
- lines.push("| Field | Type | Description |");
165
- lines.push("|-------|------|-------------|");
166
- for (const field of skill.metadata.outputSchema) {
167
- lines.push(`| \`${field.name}\` | ${field.type} | ${field.description} |`);
168
- }
169
- lines.push("");
170
- }
171
- if (skill.environment && Object.keys(skill.environment).length > 0) {
172
- lines.push("## Environment");
173
- lines.push("");
174
- lines.push("```yaml");
175
- for (const [key, val] of Object.entries(skill.environment)) {
176
- lines.push(`${key}: ${JSON.stringify(val)}`);
177
- }
178
- lines.push("```");
179
- lines.push("");
180
- }
181
- if (skill.steps.length > 0) {
182
- lines.push("## Workflow");
183
- lines.push("");
184
- let stepNum = 1;
185
- for (const step of skill.steps) {
186
- if (step.nodeType === "sequence" || step.nodeType === "selector") {
187
- lines.push(`### ${step.description || step.action}`);
188
- lines.push("");
189
- } else {
190
- const paramsStr = Object.keys(step.params).length > 0 ? ` (${Object.entries(step.params).map(([k, v]) => `${k}: ${JSON.stringify(v)}`).join(", ")})` : "";
191
- lines.push(`${stepNum}. **${step.action}**${paramsStr}`);
192
- if (step.description) {
193
- lines.push(` ${step.description}`);
194
- }
195
- stepNum++;
196
- }
197
- }
198
- lines.push("");
199
- }
200
- if (skill.objects && skill.objects.length > 0) {
201
- lines.push("## Scene Objects");
202
- lines.push("");
203
- for (const obj of skill.objects) {
204
- lines.push(`- \`${obj}\``);
205
- }
206
- lines.push("");
207
- }
208
- if (skill.tests.length > 0) {
209
- lines.push("## Tests");
210
- lines.push("");
211
- lines.push(`${skill.tests.length} built-in assertions:`);
212
- lines.push("");
213
- for (const test of skill.tests) {
214
- lines.push(`- **${test.name}**: \`${test.assert}\``);
215
- }
216
- lines.push("");
217
- }
218
- lines.push("## Installation");
219
- lines.push("");
220
- lines.push("```bash");
221
- lines.push(`# Via HoloClaw CLI`);
222
- lines.push(`hs claw install ${skill.metadata.name}`);
223
- lines.push("");
224
- lines.push("# Via ClawHub registry");
225
- lines.push(`clawhub install @holoscript/${skill.metadata.name}`);
226
- lines.push("");
227
- lines.push("# Manual: copy to compositions/skills/");
228
- lines.push(`cp ${skill.metadata.name}.hsplus compositions/skills/`);
229
- lines.push("```");
230
- lines.push("");
231
- lines.push("## Usage");
232
- lines.push("");
233
- lines.push("```bash");
234
- lines.push(`# Run standalone`);
235
- lines.push(`hs run compositions/skills/${skill.metadata.name}.hsplus`);
236
- lines.push("");
237
- lines.push("# Run as HoloClaw skill (hot-reload)");
238
- lines.push(`hs daemon compositions/holoclaw.hsplus --always-on`);
239
- lines.push("```");
240
- lines.push("");
241
- lines.push("---");
242
- lines.push("");
243
- lines.push(`*Generated by HoloScript Skill-MD Bridge v1.0.0*`);
244
- lines.push(`*Source format: .hsplus (HoloClaw native composition)*`);
245
- lines.push("");
246
- return {
247
- success: true,
248
- data: lines.join("\n"),
249
- errors,
250
- warnings
251
- };
252
- }
253
- function hsplusToSkillMd(source) {
254
- const parsed = parseHsplus(source);
255
- if (!parsed.success || !parsed.data) {
256
- return { success: false, errors: parsed.errors, warnings: parsed.warnings };
257
- }
258
- return toSkillMd(parsed.data);
259
- }
260
- function parseSkillMd(markdown) {
261
- const errors = [];
262
- const warnings = [];
263
- const frontmatter = extractFrontmatter(markdown);
264
- if (!frontmatter) {
265
- errors.push("No YAML frontmatter found. Expected --- delimited block at start of file.");
266
- return { success: false, errors, warnings };
267
- }
268
- const name = frontmatter.name;
269
- if (!name) {
270
- errors.push('Frontmatter missing required "name" field.');
271
- return { success: false, errors, warnings };
272
- }
273
- const description = frontmatter.description || "";
274
- const version = frontmatter.version || "1.0.0";
275
- const author = frontmatter.author || "HoloScript";
276
- const body = extractBody(markdown);
277
- const inputSchemaFm = parseFrontmatterSchemaList(frontmatter["input_schema"]);
278
- const outputSchemaFm = parseFrontmatterSchemaList(frontmatter["output_schema"]);
279
- const inputSchemaBody = extractInputSchemaFromMd(body);
280
- const outputSchemaBody = extractOutputSchemaFromMd(body);
281
- const inputSchema = inputSchemaFm.length > 0 ? inputSchemaFm : inputSchemaBody;
282
- const outputSchema = outputSchemaFm.length > 0 ? outputSchemaFm : outputSchemaBody;
283
- const metadata = {
284
- name,
285
- description: typeof description === "string" ? description.trim() : String(description),
286
- version,
287
- author,
288
- category: frontmatter.category,
289
- tags: frontmatter.tags,
290
- inputSchema: inputSchema.length > 0 ? inputSchema : void 0,
291
- outputSchema: outputSchema.length > 0 ? outputSchema : void 0,
292
- holoCliVersion: frontmatter["holoscript-cli"] || "5.0.0",
293
- nodeVersion: frontmatter["node-version"] || "20",
294
- license: frontmatter.license,
295
- homepage: frontmatter.homepage,
296
- repository: frontmatter.repository,
297
- userInvocable: frontmatter["user-invocable"] !== false
298
- };
299
- const traits = extractTraitsFromMd(body);
300
- const state = extractStateFromMd(body);
301
- const steps = extractStepsFromMd(body);
302
- const tests = extractTestsFromMd(body);
303
- const environment = extractEnvironmentFromMd(body);
304
- return {
305
- success: true,
306
- data: {
307
- metadata,
308
- traits: traits.length > 0 ? traits : getDefaultTraits(),
309
- state,
310
- steps,
311
- tests,
312
- environment: environment || void 0,
313
- sourceComments: []
314
- },
315
- errors,
316
- warnings
317
- };
318
- }
319
- function toHsplus(skill) {
320
- const errors = [];
321
- const warnings = [];
322
- const lines = [];
323
- lines.push(
324
- `// ${titleCase(skill.metadata.name)} -- ${skill.metadata.description.split("\n")[0]}`
325
- );
326
- if (skill.metadata.description.includes("\n")) {
327
- for (const line of skill.metadata.description.split("\n").slice(1)) {
328
- if (line.trim()) lines.push(`// ${line.trim()}`);
329
- }
330
- }
331
- lines.push(`// Installed via HoloClaw Shelf. Hot-reloads into running daemon.`);
332
- if (skill.metadata.version !== "1.0.0") {
333
- lines.push(`//`);
334
- lines.push(`// @version ${skill.metadata.version}`);
335
- }
336
- lines.push("");
337
- lines.push(`composition "${skill.metadata.name}" {`);
338
- for (const trait of skill.traits) {
339
- const configEntries = Object.entries(trait.config);
340
- if (configEntries.length === 0) {
341
- lines.push(` @${trait.name}`);
342
- } else if (configEntries.length === 1) {
343
- const [k, v] = configEntries[0];
344
- lines.push(` @${trait.name} (${k}: ${formatHsplusValue(v)})`);
345
- } else {
346
- lines.push(` @${trait.name} {`);
347
- for (const [k, v] of configEntries) {
348
- lines.push(` ${k}: ${formatHsplusValue(v)}`);
349
- }
350
- lines.push(` }`);
351
- }
352
- }
353
- lines.push("");
354
- for (const sv of skill.state) {
355
- lines.push(` state ${sv.name}: ${sv.type} = ${formatHsplusValue(sv.defaultValue)}`);
356
- }
357
- if (skill.state.length > 0) lines.push("");
358
- if (skill.environment && Object.keys(skill.environment).length > 0) {
359
- lines.push(" environment {");
360
- for (const [key, val] of Object.entries(skill.environment)) {
361
- lines.push(` ${key}: ${formatHsplusValue(val)}`);
362
- }
363
- lines.push(" }");
364
- lines.push("");
365
- }
366
- if (skill.steps.length > 0) {
367
- const topSequences = groupStepsIntoSequences(skill.steps);
368
- for (const seq of topSequences) {
369
- emitBTNode(lines, seq, 2);
370
- }
371
- lines.push("");
372
- }
373
- if (skill.tests.length > 0) {
374
- lines.push(" // -- Tests --");
375
- lines.push("");
376
- for (const test of skill.tests) {
377
- lines.push(" @test {");
378
- lines.push(` name: "${test.name}"`);
379
- if (test.setup) {
380
- lines.push(` setup: { ${test.setup} }`);
381
- }
382
- lines.push(` assert: { ${test.assert} }`);
383
- lines.push(" }");
384
- lines.push("");
385
- }
386
- }
387
- lines.push("}");
388
- lines.push("");
389
- return {
390
- success: true,
391
- data: lines.join("\n"),
392
- errors,
393
- warnings
394
- };
395
- }
396
- function skillMdToHsplus(markdown) {
397
- const parsed = parseSkillMd(markdown);
398
- if (!parsed.success || !parsed.data) {
399
- return { success: false, errors: parsed.errors, warnings: parsed.warnings };
400
- }
401
- return toHsplus(parsed.data);
402
- }
403
- function generateClawHubManifest(skill, registryUrl = "https://registry.clawhub.com") {
404
- return {
405
- name: `@holoscript/${skill.metadata.name}`,
406
- version: skill.metadata.version,
407
- description: skill.metadata.description,
408
- author: skill.metadata.author,
409
- license: skill.metadata.license || "MIT",
410
- registryUrl,
411
- tags: skill.metadata.tags,
412
- homepage: skill.metadata.homepage,
413
- repository: skill.metadata.repository,
414
- holoScript: {
415
- format: "hsplus",
416
- minCliVersion: skill.metadata.holoCliVersion || "5.0.0",
417
- traits: skill.traits.map((t) => t.name),
418
- stateVars: skill.state.map((s) => s.name),
419
- testCount: skill.tests.length,
420
- inputFields: (skill.metadata.inputSchema || []).map((f) => f.name),
421
- outputFields: (skill.metadata.outputSchema || []).map((f) => f.name)
422
- },
423
- files: [`${skill.metadata.name}.hsplus`, "SKILL.md", "clawhub.json"]
424
- };
425
- }
426
- function generateClawHubPackage(source) {
427
- const parsed = parseHsplus(source);
428
- if (!parsed.success || !parsed.data) {
429
- return { success: false, errors: parsed.errors, warnings: parsed.warnings };
430
- }
431
- const skill = parsed.data;
432
- const skillMdResult = toSkillMd(skill);
433
- if (!skillMdResult.success || !skillMdResult.data) {
434
- return { success: false, errors: skillMdResult.errors, warnings: skillMdResult.warnings };
435
- }
436
- const manifest = generateClawHubManifest(skill);
437
- const files = /* @__PURE__ */ new Map();
438
- files.set(`${skill.metadata.name}.hsplus`, source);
439
- files.set("SKILL.md", skillMdResult.data);
440
- files.set("clawhub.json", JSON.stringify(manifest, null, 2));
441
- return {
442
- success: true,
443
- data: files,
444
- errors: [],
445
- warnings: []
446
- };
447
- }
448
- function getPublishCommand(skillName, registry = "https://registry.clawhub.com") {
449
- return `clawhub publish @holoscript/${skillName} --registry ${registry}`;
450
- }
451
- function getInstallCommand(skillName, targetDir = "compositions/skills", registry = "https://registry.clawhub.com") {
452
- return `clawhub install @holoscript/${skillName} --target ${targetDir} --registry ${registry}`;
453
- }
454
- function getHsInstallCommand(skillName) {
455
- return `hs claw install ${skillName}`;
456
- }
457
- function extractLeadingComments(source) {
458
- const lines = source.split("\n");
459
- const comments = [];
460
- for (const line of lines) {
461
- const trimmed = line.trim();
462
- if (trimmed.startsWith("//")) {
463
- comments.push(trimmed.replace(/^\/\/\s?/, ""));
464
- } else if (trimmed === "" && comments.length > 0) {
465
- continue;
466
- } else {
467
- break;
468
- }
469
- }
470
- return comments;
471
- }
472
- function extractDescription(comments) {
473
- const descLines = [];
474
- for (const line of comments) {
475
- if (line.startsWith("@") || line.startsWith("*") || line === "") continue;
476
- descLines.push(line);
477
- }
478
- return descLines.join(" ").trim();
479
- }
480
- function extractTraits(source) {
481
- const traits = [];
482
- const traitRegex = /^\s{2}@(\w+)(?:\s*\(([^)]*)\))?(?:\s*\{([^}]*)\})?/gm;
483
- let match;
484
- while ((match = traitRegex.exec(source)) !== null) {
485
- const name = match[1];
486
- if (name === "test" || name === "version") continue;
487
- const config = {};
488
- const inlineConfig = match[2] || match[3];
489
- if (inlineConfig) {
490
- parseTraitConfig(inlineConfig, config);
491
- }
492
- traits.push({ name, config });
493
- }
494
- return traits;
495
- }
496
- function parseTraitConfig(configStr, config) {
497
- const pairs = configStr.split(/,|\n/).map((s) => s.trim()).filter(Boolean);
498
- for (const pair of pairs) {
499
- const colonIdx = pair.indexOf(":");
500
- if (colonIdx === -1) continue;
501
- const key = pair.slice(0, colonIdx).trim();
502
- const rawVal = pair.slice(colonIdx + 1).trim();
503
- config[key] = parseConfigValue(rawVal);
504
- }
505
- }
506
- function parseConfigValue(raw) {
507
- if (/^-?\d+(\.\d+)?$/.test(raw)) return parseFloat(raw);
508
- if (raw === "true") return true;
509
- if (raw === "false") return false;
510
- if (raw.startsWith('"') && raw.endsWith('"') || raw.startsWith("'") && raw.endsWith("'")) {
511
- return raw.slice(1, -1);
512
- }
513
- return raw;
514
- }
515
- function extractStateVars(source) {
516
- const vars = [];
517
- const inlineRegex = /^\s+state\s+(\w+)\s*:\s*(\w+)\s*=\s*(.+)$/gm;
518
- let match;
519
- while ((match = inlineRegex.exec(source)) !== null) {
520
- const name = match[1];
521
- const type = match[2];
522
- const rawVal = match[3].trim();
523
- vars.push({ name, type, defaultValue: parseStateDefault(rawVal, type) });
524
- }
525
- const blockMatch = source.match(/\bstate\s*\{([^}]*)\}/);
526
- if (blockMatch && vars.length === 0) {
527
- const blockContent = blockMatch[1];
528
- const lineRegex = /^\s*(\w+)\s*:\s*(.+)$/gm;
529
- let lineMatch;
530
- while ((lineMatch = lineRegex.exec(blockContent)) !== null) {
531
- const name = lineMatch[1];
532
- const rawVal = lineMatch[2].trim();
533
- const type = inferType(rawVal);
534
- vars.push({ name, type, defaultValue: parseStateDefault(rawVal, type) });
535
- }
536
- }
537
- return vars;
538
- }
539
- function parseStateDefault(raw, type) {
540
- const cleaned = raw.replace(/[,;]$/, "").trim();
541
- if (type === "number") return parseFloat(cleaned) || 0;
542
- if (type === "boolean") return cleaned === "true";
543
- if (cleaned.startsWith('"') && cleaned.endsWith('"')) return cleaned.slice(1, -1);
544
- if (cleaned.startsWith("'") && cleaned.endsWith("'")) return cleaned.slice(1, -1);
545
- return cleaned;
546
- }
547
- function inferType(raw) {
548
- const cleaned = raw.replace(/[,;]$/, "").trim();
549
- if (/^-?\d+(\.\d+)?$/.test(cleaned)) return "number";
550
- if (cleaned === "true" || cleaned === "false") return "boolean";
551
- return "string";
552
- }
553
- function extractBTSteps(source) {
554
- const steps = [];
555
- const seqRegex = /\b(sequence|selector)\s+"([^"]+)"\s*\{/g;
556
- let match;
557
- while ((match = seqRegex.exec(source)) !== null) {
558
- steps.push({
559
- action: match[2],
560
- description: match[2].replace(/-/g, " "),
561
- params: {},
562
- nodeType: match[1]
563
- });
564
- }
565
- const actionRegex = /\baction\s+"([^"]+)"\s*\{([^}]*)\}/g;
566
- while ((match = actionRegex.exec(source)) !== null) {
567
- const actionName = match[1];
568
- const body = match[2];
569
- const params = {};
570
- const desc = extractActionComment(body);
571
- const paramRegex = /^\s*(\w+)\s*:\s*(.+)$/gm;
572
- let paramMatch;
573
- while ((paramMatch = paramRegex.exec(body)) !== null) {
574
- const key = paramMatch[1];
575
- const val = paramMatch[2].trim();
576
- if (val.startsWith("//")) continue;
577
- params[key] = parseConfigValue(val);
578
- }
579
- steps.push({
580
- action: actionName,
581
- description: desc || actionName.replace(/_/g, " "),
582
- params,
583
- nodeType: "action"
584
- });
585
- }
586
- return steps;
587
- }
588
- function extractActionComment(body) {
589
- const commentMatch = body.match(/\/\/\s*(.+)/);
590
- return commentMatch ? commentMatch[1].trim() : "";
591
- }
592
- function extractTests(source) {
593
- const tests = [];
594
- const testStarts = [...source.matchAll(/@test\s*\{/g)];
595
- for (const startMatch of testStarts) {
596
- const startIdx = startMatch.index + startMatch[0].length;
597
- let depth = 1;
598
- let i = startIdx;
599
- while (i < source.length && depth > 0) {
600
- if (source[i] === "{") depth++;
601
- if (source[i] === "}") depth--;
602
- i++;
603
- }
604
- const block = source.slice(startIdx, i - 1);
605
- const nameMatch = block.match(/name\s*:\s*"([^"]+)"/);
606
- const assertMatch = block.match(/assert\s*:\s*\{([^}]+)\}/);
607
- const setupMatch = block.match(/setup\s*:\s*\{([^}]+)\}/);
608
- if (nameMatch && assertMatch) {
609
- tests.push({
610
- name: nameMatch[1],
611
- assert: assertMatch[1].trim(),
612
- setup: setupMatch ? setupMatch[1].trim() : void 0
613
- });
614
- }
615
- }
616
- return tests;
617
- }
618
- function extractEnvironment(source) {
619
- const envMatch = source.match(/\benvironment\s*\{([^}]*)\}/);
620
- if (!envMatch) return null;
621
- const config = {};
622
- const lineRegex = /^\s*(\w+)\s*:\s*(.+)$/gm;
623
- let match;
624
- while ((match = lineRegex.exec(envMatch[1])) !== null) {
625
- config[match[1]] = parseConfigValue(match[2].trim());
626
- }
627
- return config;
628
- }
629
- function extractObjectNames(source) {
630
- const names = [];
631
- const objRegex = /\bobject\s+"([^"]+)"\s*\{/g;
632
- let match;
633
- while ((match = objRegex.exec(source)) !== null) {
634
- names.push(match[1]);
635
- }
636
- return names;
637
- }
638
- function extractSchemaFields(source, blockName) {
639
- const fields = [];
640
- const startRegex = new RegExp(`@${blockName}\\s*\\{`);
641
- const startMatch = startRegex.exec(source);
642
- if (!startMatch) return fields;
643
- const startIdx = startMatch.index + startMatch[0].length;
644
- let depth = 1;
645
- let i = startIdx;
646
- while (i < source.length && depth > 0) {
647
- if (source[i] === "{") depth++;
648
- if (source[i] === "}") depth--;
649
- i++;
650
- }
651
- const block = source.slice(startIdx, i - 1);
652
- const lineRegex = /^\s*(\w+)\s*:\s*(\w+)(?:\s*\(required\))?(?:\s*=\s*([^\s"]+))?(?:\s*"([^"]*)")?/gm;
653
- let lineMatch;
654
- while ((lineMatch = lineRegex.exec(block)) !== null) {
655
- const name = lineMatch[1];
656
- const type = lineMatch[2];
657
- const isRequired = lineMatch[0].includes("(required)");
658
- const defaultVal = lineMatch[3] ? parseConfigValue(lineMatch[3]) : void 0;
659
- const description = lineMatch[4] || name;
660
- fields.push({
661
- name,
662
- type,
663
- required: isRequired || void 0,
664
- description,
665
- default: defaultVal
666
- });
667
- }
668
- return fields;
669
- }
670
- function extractFrontmatter(markdown) {
671
- const fmMatch = markdown.match(/^---\s*\n([\s\S]*?)\n---/);
672
- if (!fmMatch) return null;
673
- return parseSimpleYaml(fmMatch[1]);
674
- }
675
- function parseSimpleYaml(yaml) {
676
- const result = {};
677
- const lines = yaml.split("\n");
678
- let currentKey = null;
679
- let multilineValue = [];
680
- let inMultiline = false;
681
- let inListOfObjects = false;
682
- let listKey = null;
683
- let currentListItem = null;
684
- let listItems = [];
685
- for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
686
- const line = lines[lineIdx];
687
- if (inListOfObjects && listKey) {
688
- const listItemStart = line.match(/^\s{2,}-\s+(\w[\w-]*)\s*:\s*(.*)/);
689
- if (listItemStart) {
690
- if (currentListItem) listItems.push(currentListItem);
691
- currentListItem = {};
692
- const key = listItemStart[1];
693
- const val = listItemStart[2].trim();
694
- currentListItem[key] = parseConfigValue(val);
695
- continue;
696
- }
697
- const listItemCont = line.match(/^\s{4,}(\w[\w-]*)\s*:\s*(.*)/);
698
- if (listItemCont && currentListItem) {
699
- const key = listItemCont[1];
700
- const val = listItemCont[2].trim();
701
- currentListItem[key] = parseConfigValue(val);
702
- continue;
703
- }
704
- if (currentListItem) listItems.push(currentListItem);
705
- result[listKey] = listItems;
706
- inListOfObjects = false;
707
- listKey = null;
708
- currentListItem = null;
709
- listItems = [];
710
- }
711
- if (inMultiline) {
712
- if (line.match(/^\s{2,}/) && !line.match(/^\S/)) {
713
- multilineValue.push(line.trim());
714
- continue;
715
- } else {
716
- if (currentKey) {
717
- result[currentKey] = multilineValue.join(" ");
718
- }
719
- inMultiline = false;
720
- currentKey = null;
721
- multilineValue = [];
722
- }
723
- }
724
- const kvMatch = line.match(/^([a-zA-Z_][\w-]*)\s*:\s*(.*)/);
725
- if (kvMatch) {
726
- const key = kvMatch[1];
727
- const rawVal = kvMatch[2].trim();
728
- if (rawVal === ">") {
729
- currentKey = key;
730
- inMultiline = true;
731
- multilineValue = [];
732
- continue;
733
- }
734
- if (rawVal === "") {
735
- let peekIdx = lineIdx + 1;
736
- while (peekIdx < lines.length && lines[peekIdx].trim() === "") peekIdx++;
737
- if (peekIdx < lines.length && /^\s{2,}-\s/.test(lines[peekIdx])) {
738
- inListOfObjects = true;
739
- listKey = key;
740
- currentListItem = null;
741
- listItems = [];
742
- continue;
743
- }
744
- result[key] = "";
745
- continue;
746
- }
747
- if (rawVal.startsWith("[") && rawVal.endsWith("]")) {
748
- result[key] = rawVal.slice(1, -1).split(",").map((s) => s.trim()).filter(Boolean);
749
- continue;
750
- }
751
- result[key] = parseConfigValue(rawVal);
752
- }
753
- }
754
- if (inMultiline && currentKey) {
755
- result[currentKey] = multilineValue.join(" ");
756
- }
757
- if (inListOfObjects && listKey) {
758
- if (currentListItem) listItems.push(currentListItem);
759
- result[listKey] = listItems;
760
- }
761
- return result;
762
- }
763
- function extractBody(markdown) {
764
- const fmEnd = markdown.indexOf("---", 3);
765
- if (fmEnd === -1) return markdown;
766
- return markdown.slice(fmEnd + 3).trim();
767
- }
768
- function extractTraitsFromMd(body) {
769
- const traits = [];
770
- const traitsSection = extractSection(body, "Traits");
771
- if (!traitsSection) return traits;
772
- const traitRegex = /`@(\w+)`(?:\s*\(([^)]+)\))?/g;
773
- let match;
774
- while ((match = traitRegex.exec(traitsSection)) !== null) {
775
- const config = {};
776
- if (match[2]) {
777
- parseTraitConfig(match[2], config);
778
- }
779
- traits.push({ name: match[1], config });
780
- }
781
- return traits;
782
- }
783
- function extractStateFromMd(body) {
784
- const vars = [];
785
- const stateSection = extractSection(body, "State Schema");
786
- if (!stateSection) return vars;
787
- const rowRegex = /\|\s*`(\w+)`\s*\|\s*(\w+)\s*\|\s*`([^`]+)`\s*\|/g;
788
- let match;
789
- while ((match = rowRegex.exec(stateSection)) !== null) {
790
- const name = match[1];
791
- const type = match[2];
792
- const rawDefault = match[3];
793
- vars.push({
794
- name,
795
- type,
796
- defaultValue: parseStateDefault(rawDefault, type)
797
- });
798
- }
799
- return vars;
800
- }
801
- function extractStepsFromMd(body) {
802
- const steps = [];
803
- const workflowSection = extractSection(body, "Workflow");
804
- if (!workflowSection) return steps;
805
- const subsectionRegex = /###\s+(.+)/g;
806
- let match;
807
- while ((match = subsectionRegex.exec(workflowSection)) !== null) {
808
- steps.push({
809
- action: match[1].trim().toLowerCase().replace(/\s+/g, "-"),
810
- description: match[1].trim(),
811
- params: {},
812
- nodeType: "sequence"
813
- });
814
- }
815
- const stepRegex = /\d+\.\s+\*\*([^*]+)\*\*(?:\s*\(([^)]+)\))?(?:\s*\n\s+(.+))?/g;
816
- while ((match = stepRegex.exec(workflowSection)) !== null) {
817
- const params = {};
818
- if (match[2]) {
819
- parseTraitConfig(match[2], params);
820
- }
821
- steps.push({
822
- action: match[1].trim(),
823
- description: match[3]?.trim() || match[1].trim().replace(/_/g, " "),
824
- params,
825
- nodeType: "action"
826
- });
827
- }
828
- return steps;
829
- }
830
- function extractTestsFromMd(body) {
831
- const tests = [];
832
- const testsSection = extractSection(body, "Tests");
833
- if (!testsSection) return tests;
834
- const testRegex = /-\s+\*\*([^*]+)\*\*\s*:\s*`([^`]+)`/g;
835
- let match;
836
- while ((match = testRegex.exec(testsSection)) !== null) {
837
- tests.push({
838
- name: match[1].trim(),
839
- assert: match[2].trim()
840
- });
841
- }
842
- return tests;
843
- }
844
- function extractEnvironmentFromMd(body) {
845
- const envSection = extractSection(body, "Environment");
846
- if (!envSection) return null;
847
- const config = {};
848
- const codeBlockMatch = envSection.match(/```(?:yaml)?\s*\n([\s\S]*?)```/);
849
- if (codeBlockMatch) {
850
- const parsed = parseSimpleYaml(codeBlockMatch[1]);
851
- for (const [k, v] of Object.entries(parsed)) {
852
- config[k] = v;
853
- }
854
- }
855
- return Object.keys(config).length > 0 ? config : null;
856
- }
857
- function extractSection(body, heading) {
858
- const escapedHeading = heading.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
859
- const sectionRegex = new RegExp(`##\\s+${escapedHeading}\\s*
860
- ([\\s\\S]*?)(?=\\n##\\s|$)`);
861
- const match = body.match(sectionRegex);
862
- return match ? match[1].trim() : null;
863
- }
864
- function parseFrontmatterSchemaList(raw) {
865
- if (!raw) return [];
866
- if (Array.isArray(raw)) {
867
- return raw.filter(
868
- (item) => item && typeof item === "object" && "name" in item
869
- ).map((item) => ({
870
- name: String(item.name || ""),
871
- type: String(item.type || "string"),
872
- required: item.required === true || item.required === "true" || void 0,
873
- description: String(item.description || item.name || ""),
874
- default: item.default
875
- }));
876
- }
877
- return [];
878
- }
879
- function extractInputSchemaFromMd(body) {
880
- const fields = [];
881
- const section = extractSection(body, "Input Schema");
882
- if (!section) return fields;
883
- const rowRegex = /\|\s*`(\w+)`\s*\|\s*(\w+)\s*\|\s*(yes|no)\s*\|\s*([^|]+)\|/g;
884
- let match;
885
- while ((match = rowRegex.exec(section)) !== null) {
886
- const name = match[1];
887
- const type = match[2];
888
- const required = match[3] === "yes";
889
- let description = match[4].trim();
890
- let defaultVal;
891
- const defaultMatch = description.match(/\(default:\s*`([^`]+)`\)/);
892
- if (defaultMatch) {
893
- defaultVal = parseConfigValue(defaultMatch[1]);
894
- description = description.replace(/\s*\(default:\s*`[^`]+`\)/, "").trim();
895
- }
896
- fields.push({ name, type, required: required || void 0, description, default: defaultVal });
897
- }
898
- return fields;
899
- }
900
- function extractOutputSchemaFromMd(body) {
901
- const fields = [];
902
- const section = extractSection(body, "Output Schema");
903
- if (!section) return fields;
904
- const rowRegex = /\|\s*`(\w+)`\s*\|\s*(\w+)\s*\|\s*([^|]+)\|/g;
905
- let match;
906
- while ((match = rowRegex.exec(section)) !== null) {
907
- const name = match[1];
908
- const type = match[2];
909
- const description = match[3].trim();
910
- if (name === "-------" || name === "------" || description === "---") continue;
911
- fields.push({ name, type, description });
912
- }
913
- return fields;
914
- }
915
- function getDefaultTraits() {
916
- return [
917
- { name: "rate_limiter", config: {} },
918
- { name: "economy", config: { default_spend_limit: 0.1 } },
919
- { name: "timeout_guard", config: {} }
920
- ];
921
- }
922
- function formatHsplusValue(value) {
923
- if (typeof value === "string") return `"${value}"`;
924
- if (typeof value === "number") return String(value);
925
- if (typeof value === "boolean") return String(value);
926
- if (Array.isArray(value)) return `[${value.map(formatHsplusValue).join(", ")}]`;
927
- if (value === null || value === void 0) return '""';
928
- return JSON.stringify(value);
929
- }
930
- function titleCase(kebab) {
931
- return kebab.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
932
- }
933
- function groupStepsIntoSequences(steps) {
934
- const nodes = [];
935
- let currentParent = null;
936
- for (const step of steps) {
937
- if (step.nodeType === "sequence" || step.nodeType === "selector") {
938
- currentParent = {
939
- type: step.nodeType,
940
- name: step.action,
941
- description: step.description,
942
- params: {},
943
- children: []
944
- };
945
- nodes.push(currentParent);
946
- } else {
947
- const actionNode = {
948
- type: "action",
949
- name: step.action,
950
- description: step.description,
951
- params: step.params,
952
- children: []
953
- };
954
- if (currentParent) {
955
- currentParent.children.push(actionNode);
956
- } else {
957
- if (nodes.length === 0 || nodes[nodes.length - 1].type === "action") {
958
- const implicitSeq = {
959
- type: "sequence",
960
- name: "main",
961
- description: "main",
962
- params: {},
963
- children: [actionNode]
964
- };
965
- nodes.push(implicitSeq);
966
- currentParent = implicitSeq;
967
- } else {
968
- nodes[nodes.length - 1].children.push(actionNode);
969
- }
970
- }
971
- }
972
- }
973
- if (nodes.length === 0 && steps.length > 0) {
974
- const seq = {
975
- type: "sequence",
976
- name: "main",
977
- description: "main",
978
- params: {},
979
- children: steps.map((s) => ({
980
- type: "action",
981
- name: s.action,
982
- description: s.description,
983
- params: s.params,
984
- children: []
985
- }))
986
- };
987
- nodes.push(seq);
988
- }
989
- return nodes;
990
- }
991
- function emitBTNode(lines, node, indent) {
992
- const pad = " ".repeat(indent);
993
- if (node.type === "sequence" || node.type === "selector") {
994
- lines.push(`${pad}${node.type} "${node.name}" {`);
995
- for (const child of node.children) {
996
- emitBTNode(lines, child, indent + 2);
997
- }
998
- lines.push(`${pad}}`);
999
- } else {
1000
- lines.push(`${pad}action "${node.name}" {`);
1001
- if (node.description && node.description !== node.name.replace(/_/g, " ")) {
1002
- lines.push(`${pad} // ${node.description}`);
1003
- }
1004
- for (const [key, val] of Object.entries(node.params)) {
1005
- lines.push(`${pad} ${key}: ${formatHsplusValue(val)}`);
1006
- }
1007
- lines.push(`${pad}}`);
1008
- }
1009
- lines.push("");
1010
- }
1011
- function toHoloClawSkill(parsed) {
1012
- return {
1013
- id: parsed.metadata.name,
1014
- name: titleCase(parsed.metadata.name),
1015
- description: parsed.metadata.description,
1016
- version: parsed.metadata.version,
1017
- author: parsed.metadata.author,
1018
- inputs: (parsed.metadata.inputSchema || []).map((f) => ({
1019
- name: f.name,
1020
- type: f.type,
1021
- required: f.required ?? false,
1022
- description: f.description,
1023
- default: f.default
1024
- })),
1025
- outputs: (parsed.metadata.outputSchema || []).map((f) => ({
1026
- name: f.name,
1027
- type: f.type,
1028
- description: f.description
1029
- })),
1030
- sandbox: true
1031
- };
1032
- }
1033
- function fromHoloClawSkill(skill) {
1034
- const inputSchema = skill.inputs.map((i) => ({
1035
- name: i.name,
1036
- type: i.type,
1037
- required: i.required || void 0,
1038
- description: i.description,
1039
- default: i.default
1040
- }));
1041
- const outputSchema = skill.outputs.map((o) => ({
1042
- name: o.name,
1043
- type: o.type,
1044
- description: o.description
1045
- }));
1046
- return {
1047
- metadata: {
1048
- name: skill.id,
1049
- description: skill.description,
1050
- version: skill.version,
1051
- author: skill.author,
1052
- inputSchema: inputSchema.length > 0 ? inputSchema : void 0,
1053
- outputSchema: outputSchema.length > 0 ? outputSchema : void 0,
1054
- holoCliVersion: "5.0.0",
1055
- nodeVersion: "20",
1056
- userInvocable: true
1057
- },
1058
- traits: getDefaultTraits(),
1059
- state: [],
1060
- steps: [],
1061
- tests: [],
1062
- sourceComments: []
1063
- };
1064
- }
1065
- export {
1066
- fromHoloClawSkill,
1067
- generateClawHubManifest,
1068
- generateClawHubPackage,
1069
- getHsInstallCommand,
1070
- getInstallCommand,
1071
- getPublishCommand,
1072
- hsplusToSkillMd,
1073
- parseHsplus,
1074
- parseSkillMd,
1075
- skillMdToHsplus,
1076
- toHoloClawSkill,
1077
- toHsplus,
1078
- toSkillMd
1079
- };