@jaimevalasek/aioson 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +729 -232
  3. package/docs/design-previews/pt.squarespace.com-homepage.html +889 -0
  4. package/docs/integrations/sdlc-genius-boundary.md +76 -0
  5. package/docs/integrations/sdlc-genius-eval-matrix.md +75 -0
  6. package/docs/integrations/sdlc-genius-install-checklist.md +93 -0
  7. package/docs/integrations/sdlc-genius-review-samples.md +86 -0
  8. package/docs/pt/README.md +3 -0
  9. package/docs/pt/agentes.md +1 -0
  10. package/docs/pt/comandos-cli.md +888 -2
  11. package/docs/pt/design-hybrid-forge.md +255 -6
  12. package/docs/pt/devlog-pipeline.md +270 -0
  13. package/docs/pt/fluxo-artefatos.md +178 -0
  14. package/docs/pt/hooks-session-guard.md +454 -0
  15. package/docs/pt/monitor-de-contexto.md +59 -5
  16. package/docs/pt/sdd-automation-scripts.md +557 -0
  17. package/docs/pt/site-forge.md +309 -0
  18. package/docs/pt/spec-learnings-pipeline.md +265 -0
  19. package/package.json +1 -1
  20. package/src/a2a/client.js +165 -0
  21. package/src/a2a/server.js +223 -0
  22. package/src/cli.js +235 -1
  23. package/src/commands/agent-audit.js +397 -0
  24. package/src/commands/agent-export-skill.js +229 -0
  25. package/src/commands/artifact-validate.js +189 -0
  26. package/src/commands/brief-gen.js +405 -0
  27. package/src/commands/brief-validate.js +65 -0
  28. package/src/commands/classify.js +256 -0
  29. package/src/commands/context-compact.js +49 -0
  30. package/src/commands/context-health.js +175 -0
  31. package/src/commands/context-monitor.js +71 -0
  32. package/src/commands/context-trim.js +177 -0
  33. package/src/commands/detect-test-runner.js +55 -0
  34. package/src/commands/devlog-export-brains.js +27 -0
  35. package/src/commands/devlog-process.js +292 -0
  36. package/src/commands/devlog-watch.js +131 -0
  37. package/src/commands/feature-close.js +165 -0
  38. package/src/commands/gate-check.js +228 -0
  39. package/src/commands/hooks-emit.js +253 -0
  40. package/src/commands/hooks-install.js +347 -0
  41. package/src/commands/learning-auto-promote.js +195 -0
  42. package/src/commands/learning-evolve.js +18 -9
  43. package/src/commands/learning-export.js +103 -0
  44. package/src/commands/learning-rollback.js +164 -0
  45. package/src/commands/live.js +25 -1
  46. package/src/commands/pattern-detect.js +33 -0
  47. package/src/commands/preflight-context.js +30 -0
  48. package/src/commands/preflight.js +208 -0
  49. package/src/commands/pulse-update.js +130 -0
  50. package/src/commands/runner-daemon.js +274 -0
  51. package/src/commands/runner-plan.js +70 -0
  52. package/src/commands/runner-queue-from-plan.js +166 -0
  53. package/src/commands/runner-queue.js +189 -0
  54. package/src/commands/runner-run.js +129 -0
  55. package/src/commands/runtime.js +47 -1
  56. package/src/commands/self-implement-loop.js +256 -0
  57. package/src/commands/session-guard.js +218 -0
  58. package/src/commands/sizing.js +165 -0
  59. package/src/commands/skill.js +65 -0
  60. package/src/commands/spec-checkpoint.js +177 -0
  61. package/src/commands/spec-status.js +79 -0
  62. package/src/commands/spec-sync.js +190 -0
  63. package/src/commands/spec-tasks.js +288 -0
  64. package/src/commands/squad-autorun.js +1220 -0
  65. package/src/commands/squad-bus.js +217 -0
  66. package/src/commands/squad-card.js +149 -0
  67. package/src/commands/squad-daemon.js +134 -0
  68. package/src/commands/squad-dependency-graph.js +164 -0
  69. package/src/commands/squad-review.js +106 -0
  70. package/src/commands/squad-scaffold.js +55 -0
  71. package/src/commands/squad-tool-register.js +157 -0
  72. package/src/commands/state-save.js +122 -0
  73. package/src/commands/update.js +2 -0
  74. package/src/commands/verify-gate.js +572 -0
  75. package/src/commands/workflow-execute.js +241 -0
  76. package/src/constants.js +9 -0
  77. package/src/install-profile.js +2 -2
  78. package/src/install-wizard.js +3 -2
  79. package/src/installer.js +6 -0
  80. package/src/lib/health-check.js +158 -0
  81. package/src/lib/hook-protocol.js +76 -0
  82. package/src/mcp/apps/squad-dashboard/app.js +163 -0
  83. package/src/mcp/apps/squad-dashboard/index.html +261 -0
  84. package/src/mcp/apps/squad-dashboard/mcp-manifest.json +23 -0
  85. package/src/mcp/resources/squad-state.js +130 -0
  86. package/src/preflight-engine.js +443 -0
  87. package/src/runner/cascade.js +97 -0
  88. package/src/runner/cli-launcher.js +109 -0
  89. package/src/runner/plan-importer.js +63 -0
  90. package/src/runner/queue-store.js +159 -0
  91. package/src/runtime-store.js +61 -3
  92. package/src/squad/agent-teams-adapter.js +264 -0
  93. package/src/squad/brief-validator.js +350 -0
  94. package/src/squad/bus-bridge.js +140 -0
  95. package/src/squad/context-compactor.js +265 -0
  96. package/src/squad/cross-ai-synthesizer.js +250 -0
  97. package/src/squad/hooks-generator.js +196 -0
  98. package/src/squad/inter-squad-events.js +175 -0
  99. package/src/squad/intra-bus.js +345 -0
  100. package/src/squad/learning-extractor.js +213 -0
  101. package/src/squad/pattern-detector.js +365 -0
  102. package/src/squad/preflight-context.js +296 -0
  103. package/src/squad/recovery-context.js +242 -71
  104. package/src/squad/reflection.js +365 -0
  105. package/src/squad/squad-scaffold.js +177 -0
  106. package/src/squad/state-manager.js +310 -0
  107. package/src/squad/task-decomposer.js +652 -0
  108. package/src/squad/verify-gate.js +303 -0
  109. package/src/updater.js +4 -5
  110. package/src/worker-runner.js +186 -1
  111. package/template/.aioson/agents/analyst.md +62 -1
  112. package/template/.aioson/agents/architect.md +61 -1
  113. package/template/.aioson/agents/design-hybrid-forge.md +14 -0
  114. package/template/.aioson/agents/dev.md +242 -24
  115. package/template/.aioson/agents/deyvin.md +66 -8
  116. package/template/.aioson/agents/discovery-design-doc.md +44 -0
  117. package/template/.aioson/agents/genome.md +14 -0
  118. package/template/.aioson/agents/neo.md +78 -1
  119. package/template/.aioson/agents/orache.md +50 -4
  120. package/template/.aioson/agents/orchestrator.md +197 -1
  121. package/template/.aioson/agents/pm.md +35 -0
  122. package/template/.aioson/agents/product.md +50 -5
  123. package/template/.aioson/agents/profiler-enricher.md +14 -0
  124. package/template/.aioson/agents/profiler-forge.md +14 -0
  125. package/template/.aioson/agents/profiler-researcher.md +14 -0
  126. package/template/.aioson/agents/qa.md +172 -21
  127. package/template/.aioson/agents/setup.md +79 -9
  128. package/template/.aioson/agents/sheldon.md +131 -6
  129. package/template/.aioson/agents/site-forge.md +1753 -0
  130. package/template/.aioson/agents/squad.md +162 -0
  131. package/template/.aioson/agents/tester.md +53 -0
  132. package/template/.aioson/agents/ux-ui.md +34 -1
  133. package/template/.aioson/brains/README.md +128 -0
  134. package/template/.aioson/brains/_index.json +16 -0
  135. package/template/.aioson/brains/scripts/query.js +103 -0
  136. package/template/.aioson/brains/site-forge/visual-patterns.brain.json +205 -0
  137. package/template/.aioson/config.md +143 -13
  138. package/template/.aioson/constitution.md +33 -0
  139. package/template/.aioson/context/project-pulse.md +34 -0
  140. package/template/.aioson/docs/LAYERS.md +79 -0
  141. package/template/.aioson/docs/README.md +76 -0
  142. package/template/.aioson/docs/example-external-api-context.md +72 -0
  143. package/template/.aioson/locales/en/agents/architect.md +17 -0
  144. package/template/.aioson/locales/en/agents/dev.md +79 -13
  145. package/template/.aioson/locales/en/agents/orache.md +6 -0
  146. package/template/.aioson/locales/en/agents/orchestrator.md +24 -0
  147. package/template/.aioson/locales/en/agents/product.md +50 -0
  148. package/template/.aioson/locales/en/agents/sheldon.md +115 -0
  149. package/template/.aioson/locales/en/agents/squad.md +14 -0
  150. package/template/.aioson/locales/en/agents/tester.md +6 -0
  151. package/template/.aioson/locales/es/agents/analyst.md +2 -0
  152. package/template/.aioson/locales/es/agents/architect.md +19 -0
  153. package/template/.aioson/locales/es/agents/dev.md +64 -4
  154. package/template/.aioson/locales/es/agents/deyvin.md +2 -0
  155. package/template/.aioson/locales/es/agents/discovery-design-doc.md +2 -0
  156. package/template/.aioson/locales/es/agents/genome.md +2 -0
  157. package/template/.aioson/locales/es/agents/neo.md +2 -0
  158. package/template/.aioson/locales/es/agents/orache.md +2 -0
  159. package/template/.aioson/locales/es/agents/orchestrator.md +26 -0
  160. package/template/.aioson/locales/es/agents/pair.md +2 -0
  161. package/template/.aioson/locales/es/agents/pm.md +2 -0
  162. package/template/.aioson/locales/es/agents/product.md +52 -0
  163. package/template/.aioson/locales/es/agents/profiler-enricher.md +2 -0
  164. package/template/.aioson/locales/es/agents/profiler-forge.md +2 -0
  165. package/template/.aioson/locales/es/agents/profiler-researcher.md +2 -0
  166. package/template/.aioson/locales/es/agents/qa.md +2 -0
  167. package/template/.aioson/locales/es/agents/setup.md +2 -0
  168. package/template/.aioson/locales/es/agents/sheldon.md +117 -0
  169. package/template/.aioson/locales/es/agents/squad.md +16 -0
  170. package/template/.aioson/locales/es/agents/tester.md +9 -0
  171. package/template/.aioson/locales/es/agents/ux-ui.md +2 -0
  172. package/template/.aioson/locales/fr/agents/analyst.md +2 -0
  173. package/template/.aioson/locales/fr/agents/architect.md +19 -0
  174. package/template/.aioson/locales/fr/agents/dev.md +64 -4
  175. package/template/.aioson/locales/fr/agents/deyvin.md +2 -0
  176. package/template/.aioson/locales/fr/agents/discovery-design-doc.md +2 -0
  177. package/template/.aioson/locales/fr/agents/genome.md +2 -0
  178. package/template/.aioson/locales/fr/agents/neo.md +2 -0
  179. package/template/.aioson/locales/fr/agents/orache.md +2 -0
  180. package/template/.aioson/locales/fr/agents/orchestrator.md +26 -0
  181. package/template/.aioson/locales/fr/agents/pair.md +2 -0
  182. package/template/.aioson/locales/fr/agents/pm.md +2 -0
  183. package/template/.aioson/locales/fr/agents/product.md +52 -0
  184. package/template/.aioson/locales/fr/agents/profiler-enricher.md +2 -0
  185. package/template/.aioson/locales/fr/agents/profiler-forge.md +2 -0
  186. package/template/.aioson/locales/fr/agents/profiler-researcher.md +2 -0
  187. package/template/.aioson/locales/fr/agents/qa.md +2 -0
  188. package/template/.aioson/locales/fr/agents/setup.md +2 -0
  189. package/template/.aioson/locales/fr/agents/sheldon.md +117 -0
  190. package/template/.aioson/locales/fr/agents/squad.md +16 -0
  191. package/template/.aioson/locales/fr/agents/tester.md +9 -0
  192. package/template/.aioson/locales/fr/agents/ux-ui.md +2 -0
  193. package/template/.aioson/locales/pt-BR/agents/analyst.md +64 -3
  194. package/template/.aioson/locales/pt-BR/agents/architect.md +42 -0
  195. package/template/.aioson/locales/pt-BR/agents/dev.md +147 -14
  196. package/template/.aioson/locales/pt-BR/agents/deyvin.md +47 -0
  197. package/template/.aioson/locales/pt-BR/agents/neo.md +62 -1
  198. package/template/.aioson/locales/pt-BR/agents/orchestrator.md +158 -2
  199. package/template/.aioson/locales/pt-BR/agents/pm.md +95 -1
  200. package/template/.aioson/locales/pt-BR/agents/product.md +145 -18
  201. package/template/.aioson/locales/pt-BR/agents/qa.md +16 -0
  202. package/template/.aioson/locales/pt-BR/agents/setup.md +101 -18
  203. package/template/.aioson/locales/pt-BR/agents/sheldon.md +132 -1
  204. package/template/.aioson/locales/pt-BR/agents/squad.md +14 -0
  205. package/template/.aioson/locales/pt-BR/agents/tester.md +449 -0
  206. package/template/.aioson/rules/README.md +69 -0
  207. package/template/.aioson/rules/data-format-convention.md +136 -0
  208. package/template/.aioson/rules/example-monetary-values.md +30 -0
  209. package/template/.aioson/schemas/squad-manifest.schema.json +124 -3
  210. package/template/.aioson/skills/design/pt.squarespace.com/.skill-meta.json +31 -0
  211. package/template/.aioson/skills/design/pt.squarespace.com/SKILL.md +66 -0
  212. package/template/.aioson/skills/design/pt.squarespace.com/references/components.md +368 -0
  213. package/template/.aioson/skills/design/pt.squarespace.com/references/design-tokens.md +150 -0
  214. package/template/.aioson/skills/design/pt.squarespace.com/references/motion.md +270 -0
  215. package/template/.aioson/skills/design/pt.squarespace.com/references/patterns.md +189 -0
  216. package/template/.aioson/skills/design/pt.squarespace.com/references/websites.md +165 -0
  217. package/template/.aioson/skills/process/aioson-spec-driven/SKILL.md +1 -0
  218. package/template/.aioson/skills/process/aioson-spec-driven/references/analyst.md +30 -0
  219. package/template/.aioson/skills/process/aioson-spec-driven/references/architect.md +23 -0
  220. package/template/.aioson/skills/process/aioson-spec-driven/references/dev.md +47 -0
  221. package/template/.aioson/skills/process/aioson-spec-driven/references/deyvin.md +27 -0
  222. package/template/.aioson/skills/process/aioson-spec-driven/references/maintenance-and-state.md +35 -0
  223. package/template/.aioson/skills/process/aioson-spec-driven/references/product.md +25 -0
  224. package/template/.aioson/skills/process/aioson-spec-driven/references/qa.md +30 -0
  225. package/template/.aioson/skills/process/aioson-spec-driven/references/sheldon.md +25 -0
  226. package/template/.aioson/skills/process/design-hybrid-forge/SKILL.md +4 -1
  227. package/template/.aioson/skills/process/design-hybrid-forge/references/output-contract.md +15 -0
  228. package/template/.aioson/skills/process/design-hybrid-forge/references/pair-compatibility.md +32 -0
  229. package/template/.aioson/skills/process/design-hybrid-forge/references/quality-gates.md +20 -0
  230. package/template/.aioson/skills/process/simplify/SKILL.md +173 -0
  231. package/template/.aioson/skills/static/context-budget-guide.md +46 -0
  232. package/template/.aioson/skills/static/harness-sensors.md +74 -0
  233. package/template/.aioson/skills/static/multi-agent-patterns.md +43 -0
  234. package/template/.aioson/skills/static/react-motion-patterns.md +22 -0
  235. package/template/.aioson/skills/static/static-html-patterns/checklists.md +43 -0
  236. package/template/.aioson/skills/static/static-html-patterns/css-tokens.md +609 -0
  237. package/template/.aioson/skills/static/static-html-patterns/motion.md +193 -0
  238. package/template/.aioson/skills/static/static-html-patterns/premium.md +711 -0
  239. package/template/.aioson/skills/static/static-html-patterns/structure.md +209 -0
  240. package/template/.aioson/skills/static/static-html-patterns/utilities.md +190 -0
  241. package/template/.aioson/skills/static/static-html-patterns.md +58 -1913
  242. package/template/.aioson/skills/static/threejs-patterns.md +929 -0
  243. package/template/.aioson/skills/static/web-research-cache.md +112 -0
  244. package/template/.aioson/tasks/implementation-plan.md +21 -1
  245. package/template/.claude/commands/aioson/agent/design-hybrid-forge.md +5 -0
  246. package/template/.claude/commands/aioson/agent/orache.md +5 -0
  247. package/template/.claude/commands/aioson/agent/sheldon.md +5 -0
  248. package/template/.claude/commands/aioson/agent/site-forge.md +5 -0
  249. package/template/AGENTS.md +55 -3
  250. package/template/CLAUDE.md +30 -0
  251. package/template/OPENCODE.md +4 -0
  252. package/template/researchs/.gitkeep +0 -0
@@ -0,0 +1,165 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * A2A Client — Plan 81, Phase 3.2
5
+ *
6
+ * HTTP client for sending tasks/events to A2A-compatible agents
7
+ * (including other AIOSON squads in different projects).
8
+ *
9
+ * Implements Google A2A v1.0 JSON-RPC 2.0 protocol.
10
+ */
11
+
12
+ const http = require('node:http');
13
+ const https = require('node:https');
14
+ const { randomUUID } = require('node:crypto');
15
+
16
+ const DEFAULT_TIMEOUT = 30000;
17
+
18
+ /**
19
+ * Send a JSON-RPC 2.0 request to an A2A endpoint.
20
+ *
21
+ * @param {string} url — A2A endpoint URL
22
+ * @param {string} method — JSON-RPC method
23
+ * @param {object} params — Method parameters
24
+ * @param {object} [options] — { timeout }
25
+ * @returns {Promise<object>} — JSON-RPC response
26
+ */
27
+ function rpcRequest(url, method, params, options = {}) {
28
+ const { timeout = DEFAULT_TIMEOUT } = options;
29
+ const requestId = randomUUID();
30
+
31
+ const body = JSON.stringify({
32
+ jsonrpc: '2.0',
33
+ id: requestId,
34
+ method,
35
+ params
36
+ });
37
+
38
+ return new Promise((resolve, reject) => {
39
+ const parsedUrl = new URL(url);
40
+ const transport = parsedUrl.protocol === 'https:' ? https : http;
41
+
42
+ const req = transport.request({
43
+ hostname: parsedUrl.hostname,
44
+ port: parsedUrl.port,
45
+ path: parsedUrl.pathname,
46
+ method: 'POST',
47
+ headers: {
48
+ 'Content-Type': 'application/json',
49
+ 'Content-Length': Buffer.byteLength(body)
50
+ },
51
+ timeout
52
+ }, (res) => {
53
+ let data = '';
54
+ res.on('data', (chunk) => { data += chunk; });
55
+ res.on('end', () => {
56
+ try {
57
+ resolve(JSON.parse(data));
58
+ } catch {
59
+ resolve({ error: { code: -32700, message: 'Parse error', data } });
60
+ }
61
+ });
62
+ });
63
+
64
+ req.on('error', (err) => {
65
+ resolve({ error: { code: -32000, message: err.message } });
66
+ });
67
+
68
+ req.on('timeout', () => {
69
+ req.destroy();
70
+ resolve({ error: { code: -32000, message: `Request timed out after ${timeout}ms` } });
71
+ });
72
+
73
+ req.write(body);
74
+ req.end();
75
+ });
76
+ }
77
+
78
+ /**
79
+ * Discover an A2A agent by fetching its Agent Card.
80
+ *
81
+ * @param {string} baseUrl — Agent's base URL
82
+ * @returns {Promise<object|null>} — Agent Card or null
83
+ */
84
+ async function discoverAgent(baseUrl) {
85
+ const cardUrl = `${baseUrl.replace(/\/$/, '')}/.well-known/agent.json`;
86
+
87
+ return new Promise((resolve) => {
88
+ const parsedUrl = new URL(cardUrl);
89
+ const transport = parsedUrl.protocol === 'https:' ? https : http;
90
+
91
+ const req = transport.get(cardUrl, { timeout: 10000 }, (res) => {
92
+ let data = '';
93
+ res.on('data', (chunk) => { data += chunk; });
94
+ res.on('end', () => {
95
+ try {
96
+ resolve(JSON.parse(data));
97
+ } catch {
98
+ resolve(null);
99
+ }
100
+ });
101
+ });
102
+
103
+ req.on('error', () => resolve(null));
104
+ req.on('timeout', () => { req.destroy(); resolve(null); });
105
+ });
106
+ }
107
+
108
+ /**
109
+ * Send a task to an A2A agent.
110
+ *
111
+ * @param {string} agentUrl — Agent's A2A endpoint URL
112
+ * @param {object} task — { id, title, description, input }
113
+ * @returns {Promise<object>} — { ok, taskId, result, error }
114
+ */
115
+ async function sendTask(agentUrl, task) {
116
+ const taskId = task.id || randomUUID();
117
+
118
+ const response = await rpcRequest(agentUrl, 'tasks/send', {
119
+ id: taskId,
120
+ message: {
121
+ role: 'user',
122
+ parts: [
123
+ { type: 'text', text: task.description || task.title }
124
+ ]
125
+ },
126
+ metadata: {
127
+ title: task.title,
128
+ input: task.input || null
129
+ }
130
+ });
131
+
132
+ if (response.error) {
133
+ return { ok: false, taskId, error: response.error.message };
134
+ }
135
+
136
+ return { ok: true, taskId, result: response.result };
137
+ }
138
+
139
+ /**
140
+ * Publish an event to an A2A peer.
141
+ *
142
+ * @param {string} peerUrl — Peer's A2A endpoint URL
143
+ * @param {object} event — { fromSquad, event, payload }
144
+ * @returns {Promise<object>}
145
+ */
146
+ async function publishEvent(peerUrl, event) {
147
+ const response = await rpcRequest(peerUrl, 'events/publish', {
148
+ source: event.fromSquad,
149
+ type: event.event,
150
+ data: event.payload || {}
151
+ });
152
+
153
+ if (response.error) {
154
+ return { ok: false, error: response.error.message };
155
+ }
156
+
157
+ return { ok: true, id: response.result?.id };
158
+ }
159
+
160
+ module.exports = {
161
+ rpcRequest,
162
+ discoverAgent,
163
+ sendTask,
164
+ publishEvent
165
+ };
@@ -0,0 +1,223 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * A2A Server — Plan 81, Phase 3.2
5
+ *
6
+ * Micro HTTP server that exposes squad capabilities via A2A protocol.
7
+ * Receives tasks from external A2A agents and routes them to local squads.
8
+ *
9
+ * Endpoints:
10
+ * POST /a2a/{squad-slug} — JSON-RPC 2.0 task handler
11
+ * GET /.well-known/agent.json — Agent Card discovery
12
+ * GET /a2a/{squad-slug}/status — Squad status
13
+ */
14
+
15
+ const http = require('node:http');
16
+ const fs = require('node:fs/promises');
17
+ const path = require('node:path');
18
+ const { randomUUID } = require('node:crypto');
19
+
20
+ const SQUADS_DIR = path.join('.aioson', 'squads');
21
+
22
+ /**
23
+ * Create an A2A server for a project.
24
+ *
25
+ * @param {string} projectDir
26
+ * @param {object} [options] — { port, host }
27
+ * @returns {{ server, start, stop }}
28
+ */
29
+ function createA2AServer(projectDir, options = {}) {
30
+ const { port = 3847, host = '127.0.0.1' } = options;
31
+ const pendingTasks = new Map();
32
+
33
+ const server = http.createServer(async (req, res) => {
34
+ const url = new URL(req.url, `http://${host}:${port}`);
35
+
36
+ // CORS headers
37
+ res.setHeader('Access-Control-Allow-Origin', '*');
38
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
39
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
40
+
41
+ if (req.method === 'OPTIONS') {
42
+ res.writeHead(200);
43
+ res.end();
44
+ return;
45
+ }
46
+
47
+ // Agent Card discovery
48
+ if (req.method === 'GET' && url.pathname === '/.well-known/agent.json') {
49
+ return handleAgentCardDiscovery(projectDir, res);
50
+ }
51
+
52
+ // Squad status
53
+ const statusMatch = url.pathname.match(/^\/a2a\/([a-z0-9-]+)\/status$/);
54
+ if (req.method === 'GET' && statusMatch) {
55
+ return handleSquadStatus(projectDir, statusMatch[1], res);
56
+ }
57
+
58
+ // A2A JSON-RPC endpoint
59
+ const a2aMatch = url.pathname.match(/^\/a2a\/([a-z0-9-]+)$/);
60
+ if (req.method === 'POST' && a2aMatch) {
61
+ return handleJsonRpc(projectDir, a2aMatch[1], req, res, pendingTasks);
62
+ }
63
+
64
+ res.writeHead(404, { 'Content-Type': 'application/json' });
65
+ res.end(JSON.stringify({ error: 'Not Found' }));
66
+ });
67
+
68
+ return {
69
+ server,
70
+ start() {
71
+ return new Promise((resolve) => {
72
+ server.listen(port, host, () => resolve({ port, host }));
73
+ });
74
+ },
75
+ stop() {
76
+ return new Promise((resolve) => {
77
+ server.close(() => resolve());
78
+ });
79
+ },
80
+ pendingTasks
81
+ };
82
+ }
83
+
84
+ // ─── Handlers ────────────────────────────────────────────────────────────────
85
+
86
+ async function handleAgentCardDiscovery(projectDir, res) {
87
+ // Return a composite card for all squads
88
+ const squadsDir = path.join(projectDir, SQUADS_DIR);
89
+ const cards = [];
90
+
91
+ try {
92
+ const entries = await fs.readdir(squadsDir, { withFileTypes: true });
93
+ for (const entry of entries) {
94
+ if (!entry.isDirectory()) continue;
95
+ const manifestPath = path.join(squadsDir, entry.name, 'squad.manifest.json');
96
+ try {
97
+ const manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
98
+ cards.push({
99
+ slug: entry.name,
100
+ name: manifest.name || entry.name,
101
+ description: manifest.mission || manifest.goal || ''
102
+ });
103
+ } catch { /* no valid manifest */ }
104
+ }
105
+ } catch { /* no squads dir */ }
106
+
107
+ const compositeCard = {
108
+ name: 'AIOSON Project',
109
+ description: `AIOSON project with ${cards.length} squad(s)`,
110
+ version: '1.0.0',
111
+ squads: cards,
112
+ capabilities: {
113
+ streaming: false,
114
+ pushNotifications: false
115
+ }
116
+ };
117
+
118
+ res.writeHead(200, { 'Content-Type': 'application/json' });
119
+ res.end(JSON.stringify(compositeCard, null, 2));
120
+ }
121
+
122
+ async function handleSquadStatus(projectDir, squadSlug, res) {
123
+ const statePath = path.join(projectDir, SQUADS_DIR, squadSlug, 'STATE.md');
124
+
125
+ try {
126
+ const content = await fs.readFile(statePath, 'utf8');
127
+ res.writeHead(200, { 'Content-Type': 'text/markdown' });
128
+ res.end(content);
129
+ } catch {
130
+ res.writeHead(404, { 'Content-Type': 'application/json' });
131
+ res.end(JSON.stringify({ error: `Squad "${squadSlug}" not found` }));
132
+ }
133
+ }
134
+
135
+ async function handleJsonRpc(projectDir, squadSlug, req, res, pendingTasks) {
136
+ let body = '';
137
+ for await (const chunk of req) body += chunk;
138
+
139
+ let rpc;
140
+ try {
141
+ rpc = JSON.parse(body);
142
+ } catch {
143
+ res.writeHead(400, { 'Content-Type': 'application/json' });
144
+ res.end(JSON.stringify({
145
+ jsonrpc: '2.0',
146
+ error: { code: -32700, message: 'Parse error' },
147
+ id: null
148
+ }));
149
+ return;
150
+ }
151
+
152
+ const { method, params, id } = rpc;
153
+
154
+ if (method === 'tasks/send') {
155
+ const taskId = params?.id || randomUUID();
156
+ pendingTasks.set(taskId, {
157
+ id: taskId,
158
+ squadSlug,
159
+ params,
160
+ status: 'pending',
161
+ createdAt: new Date().toISOString()
162
+ });
163
+
164
+ res.writeHead(200, { 'Content-Type': 'application/json' });
165
+ res.end(JSON.stringify({
166
+ jsonrpc: '2.0',
167
+ result: {
168
+ id: taskId,
169
+ status: { state: 'submitted' },
170
+ message: `Task queued for squad "${squadSlug}"`
171
+ },
172
+ id
173
+ }));
174
+ return;
175
+ }
176
+
177
+ if (method === 'tasks/get') {
178
+ const task = pendingTasks.get(params?.id);
179
+ res.writeHead(200, { 'Content-Type': 'application/json' });
180
+ res.end(JSON.stringify({
181
+ jsonrpc: '2.0',
182
+ result: task || { error: 'Task not found' },
183
+ id
184
+ }));
185
+ return;
186
+ }
187
+
188
+ if (method === 'events/publish') {
189
+ // Route to local inter-squad-events
190
+ try {
191
+ const { publish } = require('../squad/inter-squad-events');
192
+ const eventId = await publish(projectDir, {
193
+ fromSquad: params?.source || 'a2a-external',
194
+ event: params?.type || 'a2a.event',
195
+ payload: params?.data
196
+ });
197
+
198
+ res.writeHead(200, { 'Content-Type': 'application/json' });
199
+ res.end(JSON.stringify({
200
+ jsonrpc: '2.0',
201
+ result: { id: eventId, status: 'published' },
202
+ id
203
+ }));
204
+ } catch (err) {
205
+ res.writeHead(200, { 'Content-Type': 'application/json' });
206
+ res.end(JSON.stringify({
207
+ jsonrpc: '2.0',
208
+ error: { code: -32603, message: err.message },
209
+ id
210
+ }));
211
+ }
212
+ return;
213
+ }
214
+
215
+ res.writeHead(200, { 'Content-Type': 'application/json' });
216
+ res.end(JSON.stringify({
217
+ jsonrpc: '2.0',
218
+ error: { code: -32601, message: `Method not found: ${method}` },
219
+ id
220
+ }));
221
+ }
222
+
223
+ module.exports = { createA2AServer };