society-protocol 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/dist/adapters.d.ts +101 -0
  4. package/dist/adapters.d.ts.map +1 -0
  5. package/dist/adapters.js +764 -0
  6. package/dist/adapters.js.map +1 -0
  7. package/dist/agents-md.d.ts +59 -0
  8. package/dist/agents-md.d.ts.map +1 -0
  9. package/dist/agents-md.js +204 -0
  10. package/dist/agents-md.js.map +1 -0
  11. package/dist/autoconfig.d.ts +137 -0
  12. package/dist/autoconfig.d.ts.map +1 -0
  13. package/dist/autoconfig.js +452 -0
  14. package/dist/autoconfig.js.map +1 -0
  15. package/dist/bootstrap.d.ts +68 -0
  16. package/dist/bootstrap.d.ts.map +1 -0
  17. package/dist/bootstrap.js +304 -0
  18. package/dist/bootstrap.js.map +1 -0
  19. package/dist/bridges/a2a-bridge.d.ts +156 -0
  20. package/dist/bridges/a2a-bridge.d.ts.map +1 -0
  21. package/dist/bridges/a2a-bridge.js +337 -0
  22. package/dist/bridges/a2a-bridge.js.map +1 -0
  23. package/dist/bridges/mcp-bridge.d.ts +87 -0
  24. package/dist/bridges/mcp-bridge.d.ts.map +1 -0
  25. package/dist/bridges/mcp-bridge.js +332 -0
  26. package/dist/bridges/mcp-bridge.js.map +1 -0
  27. package/dist/cache.d.ts +130 -0
  28. package/dist/cache.d.ts.map +1 -0
  29. package/dist/cache.js +257 -0
  30. package/dist/cache.js.map +1 -0
  31. package/dist/capsules.d.ts +23 -0
  32. package/dist/capsules.d.ts.map +1 -0
  33. package/dist/capsules.js +75 -0
  34. package/dist/capsules.js.map +1 -0
  35. package/dist/cli/commands.d.ts +8 -0
  36. package/dist/cli/commands.d.ts.map +1 -0
  37. package/dist/cli/commands.js +263 -0
  38. package/dist/cli/commands.js.map +1 -0
  39. package/dist/coc.d.ts +121 -0
  40. package/dist/coc.d.ts.map +1 -0
  41. package/dist/coc.js +629 -0
  42. package/dist/coc.js.map +1 -0
  43. package/dist/coc.test.d.ts +2 -0
  44. package/dist/coc.test.d.ts.map +1 -0
  45. package/dist/coc.test.js +80 -0
  46. package/dist/coc.test.js.map +1 -0
  47. package/dist/compression.d.ts +125 -0
  48. package/dist/compression.d.ts.map +1 -0
  49. package/dist/compression.js +573 -0
  50. package/dist/compression.js.map +1 -0
  51. package/dist/cot-stream.d.ts +220 -0
  52. package/dist/cot-stream.d.ts.map +1 -0
  53. package/dist/cot-stream.js +673 -0
  54. package/dist/cot-stream.js.map +1 -0
  55. package/dist/crypto-wasm.d.ts +100 -0
  56. package/dist/crypto-wasm.d.ts.map +1 -0
  57. package/dist/crypto-wasm.js +229 -0
  58. package/dist/crypto-wasm.js.map +1 -0
  59. package/dist/federation.d.ts +200 -0
  60. package/dist/federation.d.ts.map +1 -0
  61. package/dist/federation.js +691 -0
  62. package/dist/federation.js.map +1 -0
  63. package/dist/federation.test.d.ts +2 -0
  64. package/dist/federation.test.d.ts.map +1 -0
  65. package/dist/federation.test.js +71 -0
  66. package/dist/federation.test.js.map +1 -0
  67. package/dist/gateway/capability-router.d.ts +77 -0
  68. package/dist/gateway/capability-router.d.ts.map +1 -0
  69. package/dist/gateway/capability-router.js +222 -0
  70. package/dist/gateway/capability-router.js.map +1 -0
  71. package/dist/gateway/demand-spawner.d.ts +155 -0
  72. package/dist/gateway/demand-spawner.d.ts.map +1 -0
  73. package/dist/gateway/demand-spawner.js +426 -0
  74. package/dist/gateway/demand-spawner.js.map +1 -0
  75. package/dist/identity.d.ts +46 -0
  76. package/dist/identity.d.ts.map +1 -0
  77. package/dist/identity.js +102 -0
  78. package/dist/identity.js.map +1 -0
  79. package/dist/identity.test.d.ts +2 -0
  80. package/dist/identity.test.d.ts.map +1 -0
  81. package/dist/identity.test.js +45 -0
  82. package/dist/identity.test.js.map +1 -0
  83. package/dist/index.d.ts +36 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +1572 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/integration.d.ts +210 -0
  88. package/dist/integration.d.ts.map +1 -0
  89. package/dist/integration.js +1105 -0
  90. package/dist/integration.js.map +1 -0
  91. package/dist/integration.test.d.ts +2 -0
  92. package/dist/integration.test.d.ts.map +1 -0
  93. package/dist/integration.test.js +155 -0
  94. package/dist/integration.test.js.map +1 -0
  95. package/dist/knowledge.d.ts +219 -0
  96. package/dist/knowledge.d.ts.map +1 -0
  97. package/dist/knowledge.js +543 -0
  98. package/dist/knowledge.js.map +1 -0
  99. package/dist/knowledge.test.d.ts +2 -0
  100. package/dist/knowledge.test.d.ts.map +1 -0
  101. package/dist/knowledge.test.js +72 -0
  102. package/dist/knowledge.test.js.map +1 -0
  103. package/dist/latent-space.d.ts +178 -0
  104. package/dist/latent-space.d.ts.map +1 -0
  105. package/dist/latent-space.js +385 -0
  106. package/dist/latent-space.js.map +1 -0
  107. package/dist/lib.d.ts +30 -0
  108. package/dist/lib.d.ts.map +1 -0
  109. package/dist/lib.js +30 -0
  110. package/dist/lib.js.map +1 -0
  111. package/dist/mcp/server.d.ts +74 -0
  112. package/dist/mcp/server.d.ts.map +1 -0
  113. package/dist/mcp/server.js +1392 -0
  114. package/dist/mcp/server.js.map +1 -0
  115. package/dist/metrics.d.ts +98 -0
  116. package/dist/metrics.d.ts.map +1 -0
  117. package/dist/metrics.js +222 -0
  118. package/dist/metrics.js.map +1 -0
  119. package/dist/p2p.d.ts +87 -0
  120. package/dist/p2p.d.ts.map +1 -0
  121. package/dist/p2p.js +606 -0
  122. package/dist/p2p.js.map +1 -0
  123. package/dist/persona/capabilities.d.ts +17 -0
  124. package/dist/persona/capabilities.d.ts.map +1 -0
  125. package/dist/persona/capabilities.js +224 -0
  126. package/dist/persona/capabilities.js.map +1 -0
  127. package/dist/persona/domains.d.ts +22 -0
  128. package/dist/persona/domains.d.ts.map +1 -0
  129. package/dist/persona/domains.js +176 -0
  130. package/dist/persona/domains.js.map +1 -0
  131. package/dist/persona/embeddings.d.ts +40 -0
  132. package/dist/persona/embeddings.d.ts.map +1 -0
  133. package/dist/persona/embeddings.js +265 -0
  134. package/dist/persona/embeddings.js.map +1 -0
  135. package/dist/persona/engine.d.ts +79 -0
  136. package/dist/persona/engine.d.ts.map +1 -0
  137. package/dist/persona/engine.js +1087 -0
  138. package/dist/persona/engine.js.map +1 -0
  139. package/dist/persona/index.d.ts +11 -0
  140. package/dist/persona/index.d.ts.map +1 -0
  141. package/dist/persona/index.js +11 -0
  142. package/dist/persona/index.js.map +1 -0
  143. package/dist/persona/lifecycle.d.ts +17 -0
  144. package/dist/persona/lifecycle.d.ts.map +1 -0
  145. package/dist/persona/lifecycle.js +36 -0
  146. package/dist/persona/lifecycle.js.map +1 -0
  147. package/dist/persona/retrieval.d.ts +6 -0
  148. package/dist/persona/retrieval.d.ts.map +1 -0
  149. package/dist/persona/retrieval.js +122 -0
  150. package/dist/persona/retrieval.js.map +1 -0
  151. package/dist/persona/sync.d.ts +15 -0
  152. package/dist/persona/sync.d.ts.map +1 -0
  153. package/dist/persona/sync.js +92 -0
  154. package/dist/persona/sync.js.map +1 -0
  155. package/dist/persona/types.d.ts +283 -0
  156. package/dist/persona/types.d.ts.map +1 -0
  157. package/dist/persona/types.js +2 -0
  158. package/dist/persona/types.js.map +1 -0
  159. package/dist/persona/zkp/engine.d.ts +26 -0
  160. package/dist/persona/zkp/engine.d.ts.map +1 -0
  161. package/dist/persona/zkp/engine.js +370 -0
  162. package/dist/persona/zkp/engine.js.map +1 -0
  163. package/dist/persona/zkp/types.d.ts +39 -0
  164. package/dist/persona/zkp/types.d.ts.map +1 -0
  165. package/dist/persona/zkp/types.js +2 -0
  166. package/dist/persona/zkp/types.js.map +1 -0
  167. package/dist/planner.d.ts +114 -0
  168. package/dist/planner.d.ts.map +1 -0
  169. package/dist/planner.js +522 -0
  170. package/dist/planner.js.map +1 -0
  171. package/dist/proactive/checkpoints.d.ts +9 -0
  172. package/dist/proactive/checkpoints.d.ts.map +1 -0
  173. package/dist/proactive/checkpoints.js +20 -0
  174. package/dist/proactive/checkpoints.js.map +1 -0
  175. package/dist/proactive/engine.d.ts +59 -0
  176. package/dist/proactive/engine.d.ts.map +1 -0
  177. package/dist/proactive/engine.js +406 -0
  178. package/dist/proactive/engine.js.map +1 -0
  179. package/dist/proactive/scheduler.d.ts +11 -0
  180. package/dist/proactive/scheduler.d.ts.map +1 -0
  181. package/dist/proactive/scheduler.js +45 -0
  182. package/dist/proactive/scheduler.js.map +1 -0
  183. package/dist/proactive/swarm-controller.d.ts +189 -0
  184. package/dist/proactive/swarm-controller.d.ts.map +1 -0
  185. package/dist/proactive/swarm-controller.js +477 -0
  186. package/dist/proactive/swarm-controller.js.map +1 -0
  187. package/dist/proactive/swarm-registry.d.ts +13 -0
  188. package/dist/proactive/swarm-registry.d.ts.map +1 -0
  189. package/dist/proactive/swarm-registry.js +122 -0
  190. package/dist/proactive/swarm-registry.js.map +1 -0
  191. package/dist/proactive/types.d.ts +145 -0
  192. package/dist/proactive/types.d.ts.map +1 -0
  193. package/dist/proactive/types.js +25 -0
  194. package/dist/proactive/types.js.map +1 -0
  195. package/dist/registry.d.ts +35 -0
  196. package/dist/registry.d.ts.map +1 -0
  197. package/dist/registry.js +88 -0
  198. package/dist/registry.js.map +1 -0
  199. package/dist/reputation.d.ts +123 -0
  200. package/dist/reputation.d.ts.map +1 -0
  201. package/dist/reputation.js +366 -0
  202. package/dist/reputation.js.map +1 -0
  203. package/dist/reputation.test.d.ts +5 -0
  204. package/dist/reputation.test.d.ts.map +1 -0
  205. package/dist/reputation.test.js +265 -0
  206. package/dist/reputation.test.js.map +1 -0
  207. package/dist/rooms.d.ts +96 -0
  208. package/dist/rooms.d.ts.map +1 -0
  209. package/dist/rooms.js +410 -0
  210. package/dist/rooms.js.map +1 -0
  211. package/dist/sdk/client.d.ts +290 -0
  212. package/dist/sdk/client.d.ts.map +1 -0
  213. package/dist/sdk/client.js +1287 -0
  214. package/dist/sdk/client.js.map +1 -0
  215. package/dist/sdk/index.d.ts +32 -0
  216. package/dist/sdk/index.d.ts.map +1 -0
  217. package/dist/sdk/index.js +70 -0
  218. package/dist/sdk/index.js.map +1 -0
  219. package/dist/security.d.ts +230 -0
  220. package/dist/security.d.ts.map +1 -0
  221. package/dist/security.js +652 -0
  222. package/dist/security.js.map +1 -0
  223. package/dist/skills/engine.d.ts +262 -0
  224. package/dist/skills/engine.d.ts.map +1 -0
  225. package/dist/skills/engine.js +788 -0
  226. package/dist/skills/engine.js.map +1 -0
  227. package/dist/skills/engine.test.d.ts +2 -0
  228. package/dist/skills/engine.test.d.ts.map +1 -0
  229. package/dist/skills/engine.test.js +134 -0
  230. package/dist/skills/engine.test.js.map +1 -0
  231. package/dist/skills/parser.d.ts +129 -0
  232. package/dist/skills/parser.d.ts.map +1 -0
  233. package/dist/skills/parser.js +318 -0
  234. package/dist/skills/parser.js.map +1 -0
  235. package/dist/social.d.ts +149 -0
  236. package/dist/social.d.ts.map +1 -0
  237. package/dist/social.js +401 -0
  238. package/dist/social.js.map +1 -0
  239. package/dist/storage-optimized.d.ts +116 -0
  240. package/dist/storage-optimized.d.ts.map +1 -0
  241. package/dist/storage-optimized.js +264 -0
  242. package/dist/storage-optimized.js.map +1 -0
  243. package/dist/storage.d.ts +584 -0
  244. package/dist/storage.d.ts.map +1 -0
  245. package/dist/storage.js +2703 -0
  246. package/dist/storage.js.map +1 -0
  247. package/dist/storage.test.d.ts +2 -0
  248. package/dist/storage.test.d.ts.map +1 -0
  249. package/dist/storage.test.js +78 -0
  250. package/dist/storage.test.js.map +1 -0
  251. package/dist/swp.d.ts +443 -0
  252. package/dist/swp.d.ts.map +1 -0
  253. package/dist/swp.js +223 -0
  254. package/dist/swp.js.map +1 -0
  255. package/dist/swp.test.d.ts +5 -0
  256. package/dist/swp.test.d.ts.map +1 -0
  257. package/dist/swp.test.js +127 -0
  258. package/dist/swp.test.js.map +1 -0
  259. package/dist/templates.d.ts +25 -0
  260. package/dist/templates.d.ts.map +1 -0
  261. package/dist/templates.js +1048 -0
  262. package/dist/templates.js.map +1 -0
  263. package/dist/test-e2e.d.ts +14 -0
  264. package/dist/test-e2e.d.ts.map +1 -0
  265. package/dist/test-e2e.js +266 -0
  266. package/dist/test-e2e.js.map +1 -0
  267. package/dist/workers/research-worker.d.ts +19 -0
  268. package/dist/workers/research-worker.d.ts.map +1 -0
  269. package/dist/workers/research-worker.js +141 -0
  270. package/dist/workers/research-worker.js.map +1 -0
  271. package/package.json +110 -0
@@ -0,0 +1,788 @@
1
+ /**
2
+ * Society Protocol - Skills Engine v1.0
3
+ *
4
+ * Sistema de skills/plugins avançado:
5
+ * - skill.md: Skills Society Protocol (YAML + Markdown)
6
+ * - claw.md: Skills OpenClaw específicas
7
+ * - Integração multi-runtime (OpenClaw, Claude, Ollama, etc)
8
+ * - Auto-discovery e hot-reload de skills
9
+ * - Composição de skills (skills chamando skills)
10
+ */
11
+ import { EventEmitter } from 'events';
12
+ import { ulid } from 'ulid';
13
+ import { readFileSync, existsSync, readdirSync, watch } from 'fs';
14
+ import { join } from 'path';
15
+ import YAML from 'yaml';
16
+ import { spawn } from 'child_process';
17
+ import { SkillParser } from './parser.js';
18
+ export class SkillExecutionError extends Error {
19
+ code;
20
+ runtimeType;
21
+ details;
22
+ constructor(code, message, runtimeType, details) {
23
+ super(message);
24
+ this.code = code;
25
+ this.runtimeType = runtimeType;
26
+ this.details = details;
27
+ this.name = 'SkillExecutionError';
28
+ }
29
+ }
30
+ // ─── Skills Engine ───────────────────────────────────────────────
31
+ export class SkillsEngine extends EventEmitter {
32
+ storage;
33
+ identity;
34
+ skills = new Map();
35
+ clawSkills = new Map();
36
+ runtimes = new Map();
37
+ skillDir;
38
+ watchers = [];
39
+ skillParser = new SkillParser();
40
+ constructor(storage, identity, skillDir) {
41
+ super();
42
+ this.storage = storage;
43
+ this.identity = identity;
44
+ this.skillDir = skillDir || join(process.env.HOME || '', '.society', 'skills');
45
+ this.loadSkills();
46
+ this.setupWatchers();
47
+ }
48
+ // ─── Skill Loading ───────────────────────────────────────────
49
+ loadSkills() {
50
+ if (!existsSync(this.skillDir)) {
51
+ return;
52
+ }
53
+ const entries = readdirSync(this.skillDir, { withFileTypes: true });
54
+ for (const entry of entries) {
55
+ if (entry.isDirectory()) {
56
+ // Pasta de skill
57
+ const skillPath = join(this.skillDir, entry.name);
58
+ this.loadSkillFromDir(skillPath);
59
+ }
60
+ else if (entry.name.endsWith('.md')) {
61
+ // Arquivo único
62
+ this.loadSkillFromFile(join(this.skillDir, entry.name));
63
+ }
64
+ }
65
+ }
66
+ loadSkillFromDir(dir) {
67
+ const skillMd = join(dir, 'skill.md');
68
+ const clawMd = join(dir, 'claw.md');
69
+ if (existsSync(skillMd)) {
70
+ this.loadSkillFromFile(skillMd);
71
+ }
72
+ if (existsSync(clawMd)) {
73
+ this.loadClawSkillFromFile(clawMd);
74
+ }
75
+ }
76
+ loadSkillFromFile(path) {
77
+ try {
78
+ const content = readFileSync(path, 'utf-8');
79
+ const manifest = this.parseSkillMd(content);
80
+ if (manifest) {
81
+ manifest.skill.id = manifest.skill.id || this.generateSkillId(path);
82
+ this.skills.set(manifest.skill.id, manifest);
83
+ this.emit('skill:loaded', manifest.skill.id, manifest);
84
+ }
85
+ }
86
+ catch (err) {
87
+ console.error(`Failed to load skill from ${path}:`, err);
88
+ }
89
+ }
90
+ loadClawSkillFromFile(path) {
91
+ try {
92
+ const content = readFileSync(path, 'utf-8');
93
+ const clawSkill = this.parseClawMd(content);
94
+ if (clawSkill) {
95
+ const id = this.generateSkillId(path);
96
+ this.clawSkills.set(id, clawSkill);
97
+ this.emit('claw-skill:loaded', id, clawSkill);
98
+ }
99
+ }
100
+ catch (err) {
101
+ console.error(`Failed to load claw skill from ${path}:`, err);
102
+ }
103
+ }
104
+ // ─── Parsers ─────────────────────────────────────────────────
105
+ parseSkillMd(content) {
106
+ const parsed = this.skillParser.parse(content);
107
+ const skillInfo = parsed?.skill;
108
+ if (!skillInfo?.name) {
109
+ throw new Error('Invalid skill manifest: skill.name is required');
110
+ }
111
+ const id = skillInfo.id || `skill_${ulid().slice(0, 8)}`;
112
+ const nowIso = new Date().toISOString();
113
+ const runtime = parsed.runtime && typeof parsed.runtime === 'object'
114
+ ? parsed.runtime
115
+ : { type: 'local' };
116
+ const triggers = Array.isArray(parsed.triggers)
117
+ ? parsed.triggers.map((trigger) => this.normalizeTrigger(trigger))
118
+ : [{ type: 'manual', config: {} }];
119
+ const capabilities = parsed.capabilities && typeof parsed.capabilities === 'object'
120
+ ? parsed.capabilities
121
+ : {
122
+ inputs: Array.isArray(parsed.inputs)
123
+ ? parsed.inputs.map((input) => this.normalizeInputCapability(input))
124
+ : [],
125
+ outputs: Array.isArray(parsed.outputs)
126
+ ? parsed.outputs.map((output) => this.normalizeOutputCapability(output))
127
+ : []
128
+ };
129
+ return {
130
+ skill: {
131
+ id,
132
+ name: skillInfo.name,
133
+ version: skillInfo.version || '1.0.0',
134
+ description: skillInfo.description || parsed.documentation || 'Skill',
135
+ author: skillInfo.author,
136
+ license: skillInfo.license,
137
+ homepage: skillInfo.homepage,
138
+ repository: skillInfo.repository,
139
+ tags: skillInfo.tags || [],
140
+ icon: skillInfo.icon
141
+ },
142
+ runtime,
143
+ triggers,
144
+ capabilities,
145
+ actions: parsed.actions || [],
146
+ compose: parsed.compose,
147
+ society: parsed.society || {},
148
+ knowledge: parsed.knowledge,
149
+ security: parsed.security || {
150
+ sandbox: 'light',
151
+ permissions: []
152
+ },
153
+ meta: parsed.meta || {
154
+ created: nowIso,
155
+ updated: nowIso,
156
+ version: 1
157
+ }
158
+ };
159
+ }
160
+ parseClawMd(content) {
161
+ const match = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)$/);
162
+ if (!match)
163
+ return null;
164
+ const [_, yamlContent, instructionsBody] = match;
165
+ const claw = YAML.parse(yamlContent);
166
+ if (claw && instructionsBody.trim()) {
167
+ claw.instructions.system = instructionsBody.trim();
168
+ }
169
+ return claw;
170
+ }
171
+ // ─── Skill Execution ─────────────────────────────────────────
172
+ async executeSkill(skillId, inputs, context) {
173
+ const skill = this.skills.get(skillId);
174
+ if (!skill) {
175
+ throw new SkillExecutionError('not_found', `Skill ${skillId} not found`);
176
+ }
177
+ // Validar inputs
178
+ this.validateInputs(skill, inputs);
179
+ const runtime = {
180
+ id: `run_${ulid()}`,
181
+ skillId,
182
+ status: 'running',
183
+ startedAt: Date.now(),
184
+ inputs,
185
+ outputs: {},
186
+ logs: [],
187
+ artifacts: []
188
+ };
189
+ this.runtimes.set(runtime.id, runtime);
190
+ this.emit('runtime:started', runtime);
191
+ try {
192
+ await this.runRuntimeWithRetries(skill, runtime, context);
193
+ // Executar ações pós-execução
194
+ await this.executeActions(skill, runtime, context);
195
+ runtime.status = 'completed';
196
+ runtime.finishedAt = Date.now();
197
+ this.emit('runtime:completed', runtime);
198
+ }
199
+ catch (error) {
200
+ runtime.status = 'failed';
201
+ const normalized = this.normalizeExecutionError(skill.runtime.type, error);
202
+ runtime.error = normalized.message;
203
+ runtime.finishedAt = Date.now();
204
+ this.emit('runtime:failed', runtime);
205
+ throw normalized;
206
+ }
207
+ return runtime;
208
+ }
209
+ async runRuntimeWithRetries(skill, runtime, context) {
210
+ const maxRetries = this.getMaxRetries(skill);
211
+ let attempt = 0;
212
+ while (true) {
213
+ try {
214
+ await this.executeRuntime(skill, runtime, context);
215
+ return;
216
+ }
217
+ catch (error) {
218
+ if (attempt >= maxRetries) {
219
+ throw error;
220
+ }
221
+ attempt++;
222
+ runtime.logs.push(`Runtime ${skill.runtime.type} failed on attempt ${attempt}/${maxRetries + 1}. Retrying...`);
223
+ }
224
+ }
225
+ }
226
+ async executeRuntime(skill, runtime, context) {
227
+ switch (skill.runtime.type) {
228
+ case 'openclaw':
229
+ await this.executeOpenClaw(skill, runtime, context);
230
+ break;
231
+ case 'claude':
232
+ await this.executeClaude(skill, runtime, context);
233
+ break;
234
+ case 'ollama':
235
+ await this.executeOllama(skill, runtime, context);
236
+ break;
237
+ case 'http':
238
+ await this.executeHttp(skill, runtime);
239
+ break;
240
+ case 'docker':
241
+ await this.executeDocker(skill, runtime);
242
+ break;
243
+ case 'local':
244
+ await this.executeLocal(skill, runtime);
245
+ break;
246
+ default:
247
+ throw new SkillExecutionError('runtime', `Unknown runtime type: ${skill.runtime.type}`, skill.runtime.type);
248
+ }
249
+ }
250
+ getMaxRetries(skill) {
251
+ const retries = Number(skill.runtime?.retries ?? skill.security?.retries ?? 0);
252
+ if (!Number.isFinite(retries) || retries <= 0) {
253
+ return 0;
254
+ }
255
+ return Math.min(5, Math.floor(retries));
256
+ }
257
+ getRuntimeTimeoutMs(skill, fallbackMs = 30_000) {
258
+ const timeout = Number(skill.runtime?.timeoutMs ?? skill.security?.maxExecutionTime ?? fallbackMs);
259
+ if (!Number.isFinite(timeout) || timeout <= 0) {
260
+ return fallbackMs;
261
+ }
262
+ return timeout;
263
+ }
264
+ normalizeExecutionError(runtimeType, error) {
265
+ if (error instanceof SkillExecutionError) {
266
+ return error;
267
+ }
268
+ const message = error instanceof Error ? error.message : String(error);
269
+ if (/timed? out/i.test(message)) {
270
+ return new SkillExecutionError('timeout', message, runtimeType);
271
+ }
272
+ if (/fetch|network|ENOTFOUND|ECONNREFUSED/i.test(message)) {
273
+ return new SkillExecutionError('network', message, runtimeType);
274
+ }
275
+ return new SkillExecutionError('runtime', message, runtimeType);
276
+ }
277
+ async executeOpenClaw(skill, runtime, context) {
278
+ const config = skill.runtime.openclaw;
279
+ runtime.logs.push('Initializing OpenClaw runtime...');
280
+ const instructions = this.buildOpenClawInstructions(skill, runtime.inputs);
281
+ const endpoint = process.env.OPENCLAW_API_URL || 'http://localhost:8080/v1/skills/execute';
282
+ runtime.logs.push(`Calling OpenClaw endpoint ${endpoint}`);
283
+ const response = await fetch(endpoint, {
284
+ method: 'POST',
285
+ headers: {
286
+ 'Content-Type': 'application/json'
287
+ },
288
+ body: JSON.stringify({
289
+ model: config?.model,
290
+ mcp: !!config?.mcp,
291
+ tools: config?.tools || [],
292
+ instructions,
293
+ inputs: runtime.inputs,
294
+ context
295
+ }),
296
+ signal: AbortSignal.timeout(this.getRuntimeTimeoutMs(skill, 30_000))
297
+ });
298
+ if (!response.ok) {
299
+ throw new Error(`OpenClaw execution failed: ${response.status}`);
300
+ }
301
+ const payload = await response.json();
302
+ const responseData = payload && typeof payload === 'object'
303
+ ? payload
304
+ : { result: payload };
305
+ runtime.outputs = {
306
+ ...responseData,
307
+ instructions
308
+ };
309
+ }
310
+ async executeClaude(skill, runtime, context) {
311
+ const config = skill.runtime.claude;
312
+ runtime.logs.push('Initializing Claude runtime...');
313
+ const apiKey = process.env.ANTHROPIC_API_KEY;
314
+ if (!apiKey) {
315
+ throw new Error('ANTHROPIC_API_KEY is required for Claude runtime');
316
+ }
317
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
318
+ method: 'POST',
319
+ headers: {
320
+ 'content-type': 'application/json',
321
+ 'x-api-key': apiKey,
322
+ 'anthropic-version': '2023-06-01'
323
+ },
324
+ body: JSON.stringify({
325
+ model: config.model || 'claude-3-5-sonnet-latest',
326
+ max_tokens: config.maxTokens || 1024,
327
+ system: config.systemPrompt || 'You are a helpful assistant.',
328
+ messages: [
329
+ {
330
+ role: 'user',
331
+ content: JSON.stringify({
332
+ inputs: runtime.inputs,
333
+ context
334
+ })
335
+ }
336
+ ]
337
+ }),
338
+ signal: AbortSignal.timeout(this.getRuntimeTimeoutMs(skill, 30_000))
339
+ });
340
+ if (!response.ok) {
341
+ throw new Error(`Claude execution failed: ${response.status}`);
342
+ }
343
+ const data = await response.json();
344
+ const resultText = data?.content?.[0]?.text ?? JSON.stringify(data);
345
+ runtime.outputs = {
346
+ result: resultText,
347
+ model: config.model || 'claude-3-5-sonnet'
348
+ };
349
+ }
350
+ async executeOllama(skill, runtime, context) {
351
+ const config = skill.runtime.ollama;
352
+ runtime.logs.push(`Initializing Ollama with model ${config.model}...`);
353
+ const ollamaUrl = process.env.OLLAMA_URL || 'http://localhost:11434';
354
+ const response = await fetch(`${ollamaUrl}/api/generate`, {
355
+ method: 'POST',
356
+ headers: { 'Content-Type': 'application/json' },
357
+ body: JSON.stringify({
358
+ model: config.model,
359
+ prompt: JSON.stringify({
360
+ inputs: runtime.inputs,
361
+ context
362
+ }),
363
+ stream: false,
364
+ ...(config.parameters || {})
365
+ }),
366
+ signal: AbortSignal.timeout(this.getRuntimeTimeoutMs(skill, 30_000))
367
+ });
368
+ if (!response.ok) {
369
+ throw new Error(`Ollama execution failed: ${response.status}`);
370
+ }
371
+ const data = await response.json();
372
+ runtime.outputs = {
373
+ result: data?.response || '',
374
+ model: config.model
375
+ };
376
+ }
377
+ async executeHttp(skill, runtime) {
378
+ const config = skill.runtime.http;
379
+ runtime.logs.push(`Making HTTP ${config.method || 'POST'} to ${config.endpoint}...`);
380
+ const response = await fetch(config.endpoint, {
381
+ method: config.method || 'POST',
382
+ headers: {
383
+ 'Content-Type': 'application/json',
384
+ ...config.headers
385
+ },
386
+ body: JSON.stringify(runtime.inputs),
387
+ signal: AbortSignal.timeout(config.timeout ? config.timeout * 1000 : this.getRuntimeTimeoutMs(skill, 30_000))
388
+ });
389
+ if (!response.ok) {
390
+ throw new Error(`HTTP error: ${response.status}`);
391
+ }
392
+ runtime.outputs = await response.json();
393
+ }
394
+ async executeDocker(skill, runtime) {
395
+ const config = skill.runtime.docker;
396
+ runtime.logs.push(`Running Docker container ${config.image}...`);
397
+ const args = ['run', '--rm'];
398
+ for (const volume of config.volumes || []) {
399
+ args.push('-v', volume);
400
+ }
401
+ for (const [key, value] of Object.entries(config.env || {})) {
402
+ args.push('-e', `${key}=${value}`);
403
+ }
404
+ args.push(config.image);
405
+ if (config.command) {
406
+ args.push('sh', '-lc', config.command);
407
+ }
408
+ const execution = await this.runCommand('docker', args, skill.security.maxExecutionTime || 60_000);
409
+ runtime.outputs = {
410
+ result: execution.stdout.trim(),
411
+ stderr: execution.stderr.trim(),
412
+ code: execution.code,
413
+ image: config.image
414
+ };
415
+ }
416
+ async executeLocal(skill, runtime) {
417
+ runtime.logs.push('Executing local skill...');
418
+ // Executar ações definidas na skill
419
+ for (const action of skill.actions || []) {
420
+ runtime.logs.push(`Executing action: ${action.name}`);
421
+ if (action.type !== 'execute')
422
+ continue;
423
+ const command = action.config.command;
424
+ if (!command)
425
+ continue;
426
+ const execution = await this.runCommand('sh', ['-lc', command], skill.security.maxExecutionTime || 60_000);
427
+ runtime.outputs[action.name] = {
428
+ stdout: execution.stdout.trim(),
429
+ stderr: execution.stderr.trim(),
430
+ code: execution.code
431
+ };
432
+ }
433
+ runtime.outputs = {
434
+ ...runtime.outputs,
435
+ result: 'Local execution completed',
436
+ inputs: runtime.inputs
437
+ };
438
+ }
439
+ async executeActions(skill, runtime, context) {
440
+ for (const action of skill.actions || []) {
441
+ // Verificar condição
442
+ if (action.condition && !this.evaluateCondition(action.condition, runtime)) {
443
+ continue;
444
+ }
445
+ switch (action.type) {
446
+ case 'summon':
447
+ await this.executeSummonAction(skill, action, runtime, context);
448
+ break;
449
+ case 'message':
450
+ await this.executeMessageAction(skill, action, runtime, context);
451
+ break;
452
+ case 'notify':
453
+ runtime.logs.push(`Notification: ${action.config.message}`);
454
+ break;
455
+ case 'export':
456
+ runtime.logs.push(`Exporting to ${action.config.format}`);
457
+ break;
458
+ case 'compose':
459
+ await this.executeComposedSkills(skill, runtime, context);
460
+ break;
461
+ }
462
+ }
463
+ }
464
+ async executeComposedSkills(parentSkill, runtime, context) {
465
+ if (!parentSkill.compose)
466
+ return;
467
+ const { skills, sequence } = parentSkill.compose;
468
+ if (sequence === 'parallel') {
469
+ // Executar todas em paralelo
470
+ await Promise.all(skills.map(id => this.executeSkill(id, runtime.inputs, context)));
471
+ }
472
+ else if (sequence === 'sequential') {
473
+ // Executar em sequência
474
+ let composedInputs = { ...runtime.inputs };
475
+ for (const id of skills) {
476
+ const subRuntime = await this.executeSkill(id, composedInputs, context);
477
+ runtime.outputs[`compose:${id}`] = subRuntime.outputs;
478
+ // Mapear outputs para inputs da próxima
479
+ if (parentSkill.compose?.mapping) {
480
+ composedInputs = {
481
+ ...composedInputs,
482
+ ...this.applyComposeMapping(parentSkill.compose.mapping, id, subRuntime.outputs)
483
+ };
484
+ }
485
+ }
486
+ }
487
+ }
488
+ // ─── Skill Composition ───────────────────────────────────────
489
+ composeSkills(name, skillIds, options) {
490
+ const composed = {
491
+ skill: {
492
+ id: `composed_${ulid()}`,
493
+ name,
494
+ version: '1.0.0',
495
+ description: `Composed skill: ${skillIds.join(' + ')}`
496
+ },
497
+ runtime: {
498
+ type: 'local'
499
+ },
500
+ triggers: [],
501
+ capabilities: {
502
+ inputs: [],
503
+ outputs: []
504
+ },
505
+ actions: [],
506
+ compose: {
507
+ skills: skillIds,
508
+ sequence: options.sequence || 'sequential',
509
+ mapping: options.mapping
510
+ },
511
+ society: {},
512
+ security: {
513
+ sandbox: 'light',
514
+ permissions: ['compose:execute']
515
+ },
516
+ meta: {
517
+ created: new Date().toISOString(),
518
+ updated: new Date().toISOString(),
519
+ version: 1
520
+ }
521
+ };
522
+ // Agregar capabilities das skills componentes
523
+ for (const id of skillIds) {
524
+ const skill = this.skills.get(id);
525
+ if (skill) {
526
+ composed.capabilities.inputs.push(...skill.capabilities.inputs);
527
+ composed.capabilities.outputs.push(...skill.capabilities.outputs);
528
+ }
529
+ }
530
+ this.skills.set(composed.skill.id, composed);
531
+ return composed;
532
+ }
533
+ // ─── Helpers ─────────────────────────────────────────────────
534
+ normalizeTrigger(trigger) {
535
+ const rawType = String(trigger?.type || 'manual');
536
+ const type = rawType === 'schedule'
537
+ ? 'cron'
538
+ : (['webhook', 'cron', 'event', 'file', 'manual', 'api', 'mention'].includes(rawType)
539
+ ? rawType
540
+ : 'manual');
541
+ const config = trigger?.config && typeof trigger.config === 'object'
542
+ ? trigger.config
543
+ : {
544
+ source: trigger?.source,
545
+ event: trigger?.event,
546
+ cron: trigger?.cron,
547
+ condition: trigger?.condition
548
+ };
549
+ return { type: type, config };
550
+ }
551
+ normalizeInputCapability(input) {
552
+ const mappedType = this.mapExternalTypeToInputType(input?.type);
553
+ return {
554
+ name: String(input?.name || 'input'),
555
+ type: mappedType,
556
+ description: input?.description,
557
+ required: input?.required ?? false,
558
+ default: input?.default,
559
+ validation: input?.validation
560
+ };
561
+ }
562
+ normalizeOutputCapability(output) {
563
+ const mappedType = this.mapExternalTypeToOutputType(output?.type);
564
+ return {
565
+ name: String(output?.name || 'output'),
566
+ type: mappedType,
567
+ description: output?.description
568
+ };
569
+ }
570
+ mapExternalTypeToInputType(type) {
571
+ switch (type) {
572
+ case 'number':
573
+ case 'boolean':
574
+ case 'array':
575
+ case 'object':
576
+ case 'file':
577
+ case 'string':
578
+ return type;
579
+ case 'json':
580
+ return 'object';
581
+ case 'url':
582
+ case 'markdown':
583
+ default:
584
+ return 'string';
585
+ }
586
+ }
587
+ mapExternalTypeToOutputType(type) {
588
+ switch (type) {
589
+ case 'number':
590
+ case 'boolean':
591
+ case 'array':
592
+ case 'object':
593
+ case 'file':
594
+ case 'string':
595
+ return type;
596
+ case 'json':
597
+ return 'object';
598
+ case 'artifact':
599
+ return 'file';
600
+ case 'html':
601
+ case 'markdown':
602
+ default:
603
+ return 'string';
604
+ }
605
+ }
606
+ validateInputs(skill, inputs) {
607
+ for (const input of skill.capabilities.inputs) {
608
+ if (input.required && !(input.name in inputs)) {
609
+ throw new SkillExecutionError('validation', `Required input missing: ${input.name}`, skill.runtime.type);
610
+ }
611
+ if (input.name in inputs && input.validation) {
612
+ const value = inputs[input.name];
613
+ if (input.validation.pattern) {
614
+ const regex = new RegExp(input.validation.pattern);
615
+ if (!regex.test(String(value))) {
616
+ throw new SkillExecutionError('validation', `Input ${input.name} does not match pattern`, skill.runtime.type);
617
+ }
618
+ }
619
+ if (input.validation.min !== undefined && value < input.validation.min) {
620
+ throw new SkillExecutionError('validation', `Input ${input.name} below minimum`, skill.runtime.type);
621
+ }
622
+ if (input.validation.max !== undefined && value > input.validation.max) {
623
+ throw new SkillExecutionError('validation', `Input ${input.name} above maximum`, skill.runtime.type);
624
+ }
625
+ if (input.validation.enum && !input.validation.enum.includes(value)) {
626
+ throw new SkillExecutionError('validation', `Input ${input.name} not in allowed values`, skill.runtime.type);
627
+ }
628
+ }
629
+ }
630
+ }
631
+ evaluateCondition(condition, runtime) {
632
+ // Simplificado - usar engine de expressões real em produção
633
+ try {
634
+ // Substituir variáveis
635
+ const expr = condition
636
+ .replace(/inputs\.(\w+)/g, (_, key) => JSON.stringify(runtime.inputs[key]))
637
+ .replace(/outputs\.(\w+)/g, (_, key) => JSON.stringify(runtime.outputs[key]));
638
+ // Avaliar (cuidado com segurança em produção!)
639
+ return eval(expr);
640
+ }
641
+ catch {
642
+ return false;
643
+ }
644
+ }
645
+ buildOpenClawInstructions(skill, inputs) {
646
+ return `
647
+ # Task: ${skill.skill.name}
648
+
649
+ ## Inputs
650
+ ${Object.entries(inputs).map(([k, v]) => `- ${k}: ${JSON.stringify(v)}`).join('\n')}
651
+
652
+ ## Instructions
653
+ ${skill.actions.map(a => `- ${a.name}: ${a.description}`).join('\n')}
654
+ `.trim();
655
+ }
656
+ applyComposeMapping(mapping, skillId, outputs) {
657
+ const mapped = {};
658
+ for (const [target, source] of Object.entries(mapping)) {
659
+ const [sourceSkill, sourceKey] = source.split('.');
660
+ if (sourceSkill && sourceKey) {
661
+ if (sourceSkill === skillId && sourceKey in outputs) {
662
+ mapped[target] = outputs[sourceKey];
663
+ }
664
+ }
665
+ else if (source in outputs) {
666
+ mapped[target] = outputs[source];
667
+ }
668
+ }
669
+ return mapped;
670
+ }
671
+ async executeSummonAction(skill, action, runtime, context) {
672
+ const roomId = action.config.room || context?.room || skill.society.room;
673
+ if (!roomId) {
674
+ throw new Error('Summon action requires a room');
675
+ }
676
+ this.storage.createRoom(roomId, roomId, this.identity.did);
677
+ const chainId = `skill_coc_${ulid()}`;
678
+ const goal = action.config.goal || runtime.inputs.goal || skill.skill.description;
679
+ this.storage.createChain(chainId, roomId, String(goal), skill.society.template || null, this.identity.did, 'normal');
680
+ runtime.logs.push(`Summoned chain ${chainId}`);
681
+ runtime.outputs.summonedChainId = chainId;
682
+ }
683
+ async executeMessageAction(skill, action, runtime, context) {
684
+ const roomId = action.config.room || context?.room || skill.society.room;
685
+ if (!roomId) {
686
+ throw new Error('Message action requires a room');
687
+ }
688
+ this.storage.createRoom(roomId, roomId, this.identity.did);
689
+ const text = String(action.config.message || runtime.outputs.result || runtime.inputs.message || '');
690
+ const messageId = `msg_${ulid()}`;
691
+ this.storage.saveMessage(messageId, roomId, this.identity.did, this.identity.displayName, text, null, Date.now());
692
+ runtime.logs.push(`Stored message ${messageId} in room ${roomId}`);
693
+ runtime.outputs.messageId = messageId;
694
+ }
695
+ runCommand(command, args, timeoutMs) {
696
+ return new Promise((resolve, reject) => {
697
+ const child = spawn(command, args, {
698
+ stdio: ['ignore', 'pipe', 'pipe']
699
+ });
700
+ let stdout = '';
701
+ let stderr = '';
702
+ let timedOut = false;
703
+ const timer = setTimeout(() => {
704
+ timedOut = true;
705
+ child.kill('SIGTERM');
706
+ }, timeoutMs);
707
+ child.stdout.on('data', (chunk) => {
708
+ stdout += chunk.toString();
709
+ });
710
+ child.stderr.on('data', (chunk) => {
711
+ stderr += chunk.toString();
712
+ });
713
+ child.on('error', (error) => {
714
+ clearTimeout(timer);
715
+ reject(error);
716
+ });
717
+ child.on('close', (code) => {
718
+ clearTimeout(timer);
719
+ if (timedOut) {
720
+ reject(new Error(`Command timed out after ${timeoutMs}ms: ${command}`));
721
+ return;
722
+ }
723
+ if (code !== 0) {
724
+ reject(new Error(`Command failed (${command}): ${stderr.trim() || `exit ${code}`}`));
725
+ return;
726
+ }
727
+ resolve({ stdout, stderr, code: code || 0 });
728
+ });
729
+ });
730
+ }
731
+ setupWatchers() {
732
+ if (!existsSync(this.skillDir))
733
+ return;
734
+ const watcher = watch(this.skillDir, { recursive: true }, (event, filename) => {
735
+ if (filename?.endsWith('.md')) {
736
+ console.log(`Skill file changed: ${filename}`);
737
+ // Recarregar skill
738
+ const fullPath = join(this.skillDir, filename);
739
+ if (existsSync(fullPath)) {
740
+ if (filename.includes('claw')) {
741
+ this.loadClawSkillFromFile(fullPath);
742
+ }
743
+ else {
744
+ this.loadSkillFromFile(fullPath);
745
+ }
746
+ }
747
+ }
748
+ });
749
+ this.watchers.push(watcher);
750
+ }
751
+ generateSkillId(path) {
752
+ const basename = path.split('/').pop()?.replace(/\.md$/, '') || 'skill';
753
+ return `skill_${basename}_${ulid().slice(0, 8)}`;
754
+ }
755
+ // ─── Public API ──────────────────────────────────────────────
756
+ getSkill(id) {
757
+ return this.skills.get(id);
758
+ }
759
+ getClawSkill(id) {
760
+ return this.clawSkills.get(id);
761
+ }
762
+ listSkills() {
763
+ return Array.from(this.skills.values());
764
+ }
765
+ listClawSkills() {
766
+ return Array.from(this.clawSkills.entries()).map(([id, skill]) => ({ id, skill }));
767
+ }
768
+ searchSkills(query) {
769
+ const q = query.toLowerCase();
770
+ return this.listSkills().filter(s => s.skill.name.toLowerCase().includes(q) ||
771
+ s.skill.description.toLowerCase().includes(q) ||
772
+ s.skill.tags?.some(t => t.toLowerCase().includes(q)));
773
+ }
774
+ getRuntime(id) {
775
+ return this.runtimes.get(id);
776
+ }
777
+ listRuntimes() {
778
+ return Array.from(this.runtimes.values());
779
+ }
780
+ stop() {
781
+ for (const watcher of this.watchers) {
782
+ watcher.close();
783
+ }
784
+ this.watchers = [];
785
+ }
786
+ }
787
+ // Classes already exported via 'export class'
788
+ //# sourceMappingURL=engine.js.map