@julioventura/opensquad 0.1.17

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 (247) hide show
  1. package/README.md +433 -0
  2. package/_opensquad/config/playwright.config.json +11 -0
  3. package/_opensquad/core/architect.agent.yaml +112 -0
  4. package/_opensquad/core/best-practices/_catalog.yaml +126 -0
  5. package/_opensquad/core/best-practices/blog-post.md +132 -0
  6. package/_opensquad/core/best-practices/blog-seo.md +127 -0
  7. package/_opensquad/core/best-practices/brand-resolution-checklist.md +172 -0
  8. package/_opensquad/core/best-practices/copywriting.md +441 -0
  9. package/_opensquad/core/best-practices/data-analysis.md +401 -0
  10. package/_opensquad/core/best-practices/email-newsletter.md +118 -0
  11. package/_opensquad/core/best-practices/email-sales.md +110 -0
  12. package/_opensquad/core/best-practices/image-design.md +348 -0
  13. package/_opensquad/core/best-practices/instagram-feed.md +235 -0
  14. package/_opensquad/core/best-practices/instagram-reels.md +112 -0
  15. package/_opensquad/core/best-practices/instagram-stories.md +107 -0
  16. package/_opensquad/core/best-practices/linkedin-article.md +116 -0
  17. package/_opensquad/core/best-practices/linkedin-post.md +121 -0
  18. package/_opensquad/core/best-practices/researching.md +349 -0
  19. package/_opensquad/core/best-practices/review.md +269 -0
  20. package/_opensquad/core/best-practices/run-recovery.md +61 -0
  21. package/_opensquad/core/best-practices/social-networks-publishing.md +327 -0
  22. package/_opensquad/core/best-practices/squad-creation-checklist.md +32 -0
  23. package/_opensquad/core/best-practices/strategist.md +344 -0
  24. package/_opensquad/core/best-practices/technical-writing.md +365 -0
  25. package/_opensquad/core/best-practices/twitter-post.md +105 -0
  26. package/_opensquad/core/best-practices/twitter-thread.md +122 -0
  27. package/_opensquad/core/best-practices/whatsapp-broadcast.md +107 -0
  28. package/_opensquad/core/best-practices/youtube-script.md +122 -0
  29. package/_opensquad/core/best-practices/youtube-shorts.md +112 -0
  30. package/_opensquad/core/defaults/youtube-video-assembly.json +84 -0
  31. package/_opensquad/core/prompts/build.prompt.md +613 -0
  32. package/_opensquad/core/prompts/design.prompt.md +606 -0
  33. package/_opensquad/core/prompts/discovery.prompt.md +377 -0
  34. package/_opensquad/core/prompts/sherlock-instagram.md +123 -0
  35. package/_opensquad/core/prompts/sherlock-linkedin.md +73 -0
  36. package/_opensquad/core/prompts/sherlock-shared.md +684 -0
  37. package/_opensquad/core/prompts/sherlock-twitter.md +78 -0
  38. package/_opensquad/core/prompts/sherlock-youtube.md +85 -0
  39. package/_opensquad/core/runner.pipeline.md +743 -0
  40. package/_opensquad/core/skills.engine.md +384 -0
  41. package/bin/opensquad.js +108 -0
  42. package/dashboard/index.html +15 -0
  43. package/dashboard/package-lock.json +1964 -0
  44. package/dashboard/package.json +28 -0
  45. package/dashboard/public/assets/avatars/Female1_1wave.png +0 -0
  46. package/dashboard/public/assets/avatars/Female1_2wave.png +0 -0
  47. package/dashboard/public/assets/avatars/Female1_blink.png +0 -0
  48. package/dashboard/public/assets/avatars/Female1_talk.png +0 -0
  49. package/dashboard/public/assets/avatars/Female2_1wave.png +0 -0
  50. package/dashboard/public/assets/avatars/Female2_2wave.png +0 -0
  51. package/dashboard/public/assets/avatars/Female2_blink.png +0 -0
  52. package/dashboard/public/assets/avatars/Female2_talk.png +0 -0
  53. package/dashboard/public/assets/avatars/Female3_blink.png +0 -0
  54. package/dashboard/public/assets/avatars/Female3_talk.png +0 -0
  55. package/dashboard/public/assets/avatars/Female3_wave.png +0 -0
  56. package/dashboard/public/assets/avatars/Female4_blink.png +0 -0
  57. package/dashboard/public/assets/avatars/Female4_talk.png +0 -0
  58. package/dashboard/public/assets/avatars/Female4_wave.png +0 -0
  59. package/dashboard/public/assets/avatars/Female5_blink.png +0 -0
  60. package/dashboard/public/assets/avatars/Female5_talk.png +0 -0
  61. package/dashboard/public/assets/avatars/Female5_wave.png +0 -0
  62. package/dashboard/public/assets/avatars/Female6_blink.png +0 -0
  63. package/dashboard/public/assets/avatars/Female6_talk.png +0 -0
  64. package/dashboard/public/assets/avatars/Female6_wave.png +0 -0
  65. package/dashboard/public/assets/avatars/Male1_1wave.png +0 -0
  66. package/dashboard/public/assets/avatars/Male1_2wave.png +0 -0
  67. package/dashboard/public/assets/avatars/Male1_blink.png +0 -0
  68. package/dashboard/public/assets/avatars/Male1_talk.png +0 -0
  69. package/dashboard/public/assets/avatars/Male2_1wave.png +0 -0
  70. package/dashboard/public/assets/avatars/Male2_2wave.png +0 -0
  71. package/dashboard/public/assets/avatars/Male2_blink.png +0 -0
  72. package/dashboard/public/assets/avatars/Male2_talk.png +0 -0
  73. package/dashboard/public/assets/avatars/Male3_blink.png +0 -0
  74. package/dashboard/public/assets/avatars/Male3_talk.png +0 -0
  75. package/dashboard/public/assets/avatars/Male3_wave.png +0 -0
  76. package/dashboard/public/assets/avatars/Male4_blink.png +0 -0
  77. package/dashboard/public/assets/avatars/Male4_talk.png +0 -0
  78. package/dashboard/public/assets/avatars/Male4_wave.png +0 -0
  79. package/dashboard/public/assets/desks/desktop_set_black_down.png +0 -0
  80. package/dashboard/public/assets/desks/desktop_set_black_down_coding-1.png +0 -0
  81. package/dashboard/public/assets/desks/desktop_set_black_down_coding.png +0 -0
  82. package/dashboard/public/assets/desks/desktop_set_black_up.png +0 -0
  83. package/dashboard/public/assets/desks/desktop_set_white_down.png +0 -0
  84. package/dashboard/public/assets/desks/desktop_set_white_down_coding-1.png +0 -0
  85. package/dashboard/public/assets/desks/desktop_set_white_down_coding.png +0 -0
  86. package/dashboard/public/assets/desks/desktop_set_white_up.png +0 -0
  87. package/dashboard/public/assets/furniture/armchair_tan.png +0 -0
  88. package/dashboard/public/assets/furniture/armchair_tan_down.png +0 -0
  89. package/dashboard/public/assets/furniture/backpack_blue.png +0 -0
  90. package/dashboard/public/assets/furniture/backpack_red.png +0 -0
  91. package/dashboard/public/assets/furniture/blinds.png +0 -0
  92. package/dashboard/public/assets/furniture/blinds_large_closed_white.png +0 -0
  93. package/dashboard/public/assets/furniture/bookshelf.png +0 -0
  94. package/dashboard/public/assets/furniture/bookshelf_purple_tall.png +0 -0
  95. package/dashboard/public/assets/furniture/bulletin_board.png +0 -0
  96. package/dashboard/public/assets/furniture/clock.png +0 -0
  97. package/dashboard/public/assets/furniture/coffee_mug.png +0 -0
  98. package/dashboard/public/assets/furniture/coffee_mug_blue.png +0 -0
  99. package/dashboard/public/assets/furniture/coffee_table.png +0 -0
  100. package/dashboard/public/assets/furniture/coffeepot_right.png +0 -0
  101. package/dashboard/public/assets/furniture/coffeetable_black_horizontal.png +0 -0
  102. package/dashboard/public/assets/furniture/couch.png +0 -0
  103. package/dashboard/public/assets/furniture/couch_tan_down.png +0 -0
  104. package/dashboard/public/assets/furniture/cushion_blue.png +0 -0
  105. package/dashboard/public/assets/furniture/cushion_tan.png +0 -0
  106. package/dashboard/public/assets/furniture/desk_wood.png +0 -0
  107. package/dashboard/public/assets/furniture/fancy_rug.png +0 -0
  108. package/dashboard/public/assets/furniture/fancy_rug_wide.png +0 -0
  109. package/dashboard/public/assets/furniture/flowers1.png +0 -0
  110. package/dashboard/public/assets/furniture/flowers2.png +0 -0
  111. package/dashboard/public/assets/furniture/lamp_tan.png +0 -0
  112. package/dashboard/public/assets/furniture/lantern.png +0 -0
  113. package/dashboard/public/assets/furniture/monstera.png +0 -0
  114. package/dashboard/public/assets/furniture/monstera_small.png +0 -0
  115. package/dashboard/public/assets/furniture/picture_frame.png +0 -0
  116. package/dashboard/public/assets/furniture/plant1.png +0 -0
  117. package/dashboard/public/assets/furniture/plant2.png +0 -0
  118. package/dashboard/public/assets/furniture/plant3.png +0 -0
  119. package/dashboard/public/assets/furniture/plant_poof.png +0 -0
  120. package/dashboard/public/assets/furniture/plant_spindly.png +0 -0
  121. package/dashboard/public/assets/furniture/poster_blue.png +0 -0
  122. package/dashboard/public/assets/furniture/rug.png +0 -0
  123. package/dashboard/public/assets/furniture/succulent_blue.png +0 -0
  124. package/dashboard/public/assets/furniture/succulent_green.png +0 -0
  125. package/dashboard/public/assets/furniture/treasurechest_closed_gold.png +0 -0
  126. package/dashboard/public/assets/furniture/water_cooler_better.png +0 -0
  127. package/dashboard/public/assets/furniture/whiteboard.png +0 -0
  128. package/dashboard/public/assets/furniture/whiteboard_stand_graph.png +0 -0
  129. package/dashboard/public/assets/furniture/window_blinds_open.png +0 -0
  130. package/dashboard/src/App.tsx +46 -0
  131. package/dashboard/src/components/RunDashboardButton.tsx +92 -0
  132. package/dashboard/src/components/SquadCard.tsx +49 -0
  133. package/dashboard/src/components/SquadSelector.tsx +67 -0
  134. package/dashboard/src/components/StatusBadge.tsx +32 -0
  135. package/dashboard/src/components/StatusBar.tsx +116 -0
  136. package/dashboard/src/hooks/useSquadSocket.ts +135 -0
  137. package/dashboard/src/lib/formatTime.ts +16 -0
  138. package/dashboard/src/lib/normalizeState.ts +25 -0
  139. package/dashboard/src/main.tsx +10 -0
  140. package/dashboard/src/office/AgentSprite.ts +241 -0
  141. package/dashboard/src/office/OfficeScene.ts +153 -0
  142. package/dashboard/src/office/PhaserGame.tsx +80 -0
  143. package/dashboard/src/office/RoomBuilder.ts +190 -0
  144. package/dashboard/src/office/assetKeys.ts +150 -0
  145. package/dashboard/src/office/palette.ts +32 -0
  146. package/dashboard/src/plugin/squadWatcher.ts +397 -0
  147. package/dashboard/src/store/useSquadStore.ts +56 -0
  148. package/dashboard/src/styles/globals.css +36 -0
  149. package/dashboard/src/types/state.ts +63 -0
  150. package/dashboard/src/vite-env.d.ts +1 -0
  151. package/dashboard/tsconfig.json +24 -0
  152. package/dashboard/vite.config.ts +13 -0
  153. package/package.json +59 -0
  154. package/public/sfx/slide-transition-sfx.mp3 +0 -0
  155. package/skills/README.md +84 -0
  156. package/skills/apify/SKILL.md +55 -0
  157. package/skills/blotato/SKILL.md +63 -0
  158. package/skills/canva/SKILL.md +60 -0
  159. package/skills/higgsfield/SKILL.md +147 -0
  160. package/skills/image-ai-generator/SKILL.md +124 -0
  161. package/skills/image-ai-generator/scripts/generate.py +175 -0
  162. package/skills/image-creator/SKILL.md +166 -0
  163. package/skills/image-creator/editorial-slide-template.js +645 -0
  164. package/skills/image-fetcher/SKILL.md +91 -0
  165. package/skills/imgbb-uploader/SKILL.md +73 -0
  166. package/skills/imgbb-uploader/scripts/upload.js +125 -0
  167. package/skills/instagram-publisher/README.md +36 -0
  168. package/skills/instagram-publisher/SKILL.md +231 -0
  169. package/skills/instagram-publisher/scripts/publish-playwright.js +418 -0
  170. package/skills/instagram-publisher/scripts/publish.js +521 -0
  171. package/skills/opensquad-agent-creator/SKILL.md +192 -0
  172. package/skills/opensquad-skill-creator/SKILL.md +420 -0
  173. package/skills/opensquad-skill-creator/agents/analyzer.md +274 -0
  174. package/skills/opensquad-skill-creator/agents/comparator.md +202 -0
  175. package/skills/opensquad-skill-creator/agents/grader.md +223 -0
  176. package/skills/opensquad-skill-creator/assets/eval_review.html +146 -0
  177. package/skills/opensquad-skill-creator/eval-viewer/generate_review.py +471 -0
  178. package/skills/opensquad-skill-creator/eval-viewer/viewer.html +1325 -0
  179. package/skills/opensquad-skill-creator/references/schemas.md +430 -0
  180. package/skills/opensquad-skill-creator/references/skill-format.md +235 -0
  181. package/skills/opensquad-skill-creator/scripts/__init__.py +0 -0
  182. package/skills/opensquad-skill-creator/scripts/aggregate_benchmark.py +401 -0
  183. package/skills/opensquad-skill-creator/scripts/quick_validate.py +103 -0
  184. package/skills/opensquad-skill-creator/scripts/run_eval.py +310 -0
  185. package/skills/opensquad-skill-creator/scripts/utils.py +47 -0
  186. package/skills/pdf-extractor/SKILL.md +57 -0
  187. package/skills/pdf-extractor/scripts/extract.py +82 -0
  188. package/skills/resend/SKILL.md +80 -0
  189. package/skills/run-dashboard/README.md +93 -0
  190. package/skills/run-dashboard/SKILL.md +173 -0
  191. package/skills/run-dashboard/scripts/finalize-state.js +273 -0
  192. package/skills/run-dashboard/scripts/generate.js +1296 -0
  193. package/skills/run-dashboard/scripts/serve.js +135 -0
  194. package/skills/run-dashboard/templates/run-dashboard-simple.template.html +191 -0
  195. package/skills/run-dashboard/templates/run-dashboard.template.html +1164 -0
  196. package/skills/smtp-sender/SKILL.md +88 -0
  197. package/skills/smtp-sender/scripts/send.js +478 -0
  198. package/skills/template-designer/SKILL.md +201 -0
  199. package/skills/template-designer/base-templates/model-a.html +27 -0
  200. package/skills/template-designer/base-templates/model-b.html +31 -0
  201. package/skills/template-designer/base-templates/model-c.html +42 -0
  202. package/skills/youtube-publisher/SKILL.md +232 -0
  203. package/skills/youtube-publisher/scripts/publish.js +2078 -0
  204. package/src/agents-cli.js +158 -0
  205. package/src/agents.js +134 -0
  206. package/src/i18n.js +48 -0
  207. package/src/init.js +442 -0
  208. package/src/locales/en.json +79 -0
  209. package/src/locales/es.json +78 -0
  210. package/src/locales/pt-BR.json +78 -0
  211. package/src/logger.js +38 -0
  212. package/src/prompt.js +46 -0
  213. package/src/readme/README.md +146 -0
  214. package/src/runs.js +318 -0
  215. package/src/skills-cli.js +157 -0
  216. package/src/skills.js +146 -0
  217. package/src/supabase-cli.js +584 -0
  218. package/src/update.js +169 -0
  219. package/templates/_opensquad/.opensquad-version +1 -0
  220. package/templates/_opensquad/_investigations/.gitkeep +0 -0
  221. package/templates/ide-templates/antigravity/.agent/rules/opensquad.md +68 -0
  222. package/templates/ide-templates/antigravity/.agent/workflows/opensquad.md +102 -0
  223. package/templates/ide-templates/claude-code/.claude/skills/opensquad/SKILL.md +182 -0
  224. package/templates/ide-templates/claude-code/.mcp.json +8 -0
  225. package/templates/ide-templates/claude-code/CLAUDE.md +57 -0
  226. package/templates/ide-templates/codex/.agents/skills/opensquad/SKILL.md +6 -0
  227. package/templates/ide-templates/codex/AGENTS.md +120 -0
  228. package/templates/ide-templates/cursor/.cursor/commands/opensquad.md +9 -0
  229. package/templates/ide-templates/cursor/.cursor/mcp.json +8 -0
  230. package/templates/ide-templates/cursor/.cursor/rules/opensquad.mdc +62 -0
  231. package/templates/ide-templates/cursor/.cursorignore +3 -0
  232. package/templates/ide-templates/gemini-cli/.gemini/settings.json +8 -0
  233. package/templates/ide-templates/gemini-cli/.gemini/skills/opensquad/SKILL.md +186 -0
  234. package/templates/ide-templates/gemini-cli/GEMINI.md +57 -0
  235. package/templates/ide-templates/opencode/.opencode/commands/opensquad.md +9 -0
  236. package/templates/ide-templates/opencode/AGENTS.md +120 -0
  237. package/templates/ide-templates/qwen-code/.qwen/settings.json +8 -0
  238. package/templates/ide-templates/qwen-code/.qwen/skills/opensquad/SKILL.md +182 -0
  239. package/templates/ide-templates/qwen-code/QWEN.md +57 -0
  240. package/templates/ide-templates/trae/.trae/mcp.json +8 -0
  241. package/templates/ide-templates/trae/.trae/rules/opensquad.md +64 -0
  242. package/templates/ide-templates/vscode-copilot/.github/copilot-instructions.md +59 -0
  243. package/templates/ide-templates/vscode-copilot/.github/prompts/opensquad.prompt.md +209 -0
  244. package/templates/ide-templates/vscode-copilot/.vscode/mcp.json +8 -0
  245. package/templates/ide-templates/vscode-copilot/.vscode/settings.json +3 -0
  246. package/templates/package.json +8 -0
  247. package/templates/squads/.gitkeep +0 -0
@@ -0,0 +1,78 @@
1
+ {
2
+ "welcome": "Bem-vindo! Vamos configurar o Opensquad para o seu projeto.",
3
+ "askName": "Qual é o seu nome? → ",
4
+ "atLeastOneIde": "Selecione pelo menos uma IDE.",
5
+ "chooseIdes": "Quais IDEs/ferramentas você usa? (selecione todas que usa)",
6
+ "step1Codex": "1. Veja AGENTS.md na raiz do projeto para instruções do Codex",
7
+ "step1Antigravity": "1. Abra o Antigravity, digite / no chat e selecione opensquad para começar.",
8
+ "step1Cursor": "1. Abra o Cursor, digite / no chat e selecione opensquad para começar.",
9
+ "step1Opencode": "1. Abra o OpenCode e digite /opensquad para começar.",
10
+ "ideNotAvailable": "⚠️ \"{label}\" ainda não está disponível. Escolha outra opção.",
11
+ "enterNumber": "Por favor, digite um número entre 1 e {max}.",
12
+ "alreadyInitialized": "⚠️ Opensquad já está inicializado neste diretório.",
13
+ "alreadyInitializedHint": "Use o Claude Code e digite /opensquad para começar.",
14
+ "createdFile": "📄 Criado {path}",
15
+ "success": "✅ Opensquad inicializado com sucesso!",
16
+ "nextSteps": "Próximos passos:",
17
+ "step1ClaudeCode": "1. Abra este diretório no Claude Code",
18
+ "step2ClaudeCode": "2. Digite /opensquad para iniciar o assistente",
19
+ "step3ClaudeCode": "3. Siga as instruções para configurar o perfil da sua empresa",
20
+ "comingSoon": "em breve",
21
+ "updateNotInitialized": "Nenhuma instalação do Opensquad encontrada. Execute 'init' primeiro.",
22
+ "updateStarting": "Atualizando Opensquad {old} → {new}...",
23
+ "updateStartingUnknown": "Atualizando Opensquad (versão desconhecida) → {new}...",
24
+ "updatedFile": "📄 Atualizado {path}",
25
+ "updateSuccess": "✅ Opensquad {version} instalado com sucesso!",
26
+ "updatePreserved": "✓ Preservado: _memory/, _investigations/, squads/",
27
+ "updateFileCount": "✓ Atualizados: {count} arquivos do sistema",
28
+ "updateLatestHint": "💡 Dica: Use 'npx @julioventura/opensquad@latest update' para sempre obter a versão mais recente.",
29
+ "skillsNotInitialized": "Instalação Opensquad não encontrada. Execute 'init' primeiro.",
30
+ "skillsFetching": "Buscando registro de skills...",
31
+ "skillsInstalledHeader": "Instaladas:",
32
+ "skillsAvailableHeader": "Disponíveis:",
33
+ "skillsNoneInstalled": "Nenhuma skill instalada ainda.",
34
+ "skillsNoneAvailable": "Nenhuma skill disponível no registro.",
35
+ "skillsInstallHint": "Instale com: npx @julioventura/opensquad install <id>",
36
+ "skillsInstalling": "Instalando {id}...",
37
+ "skillsInstalled": "✅ Instalada: {id}",
38
+ "skillsAlreadyInstalled": "⚠️ {id} já está instalada. Reinstalar? (s/n) ",
39
+ "skillsReinstalled": "✅ Reinstalada: {id}",
40
+ "skillsRemoving": "Removendo {id}...",
41
+ "skillsRemoved": "✅ Removida: {id}",
42
+ "skillsNotInstalled": "⚠️ {id} não está instalada.",
43
+ "skillsUpdating": "Atualizando todas as skills instaladas...",
44
+ "skillsUpdateDone": "✅ {count} skill(s) atualizada(s).",
45
+ "skillsUpdateNone": "Nenhuma skill instalada para atualizar.",
46
+ "skillsError": "❌ Erro: {message}",
47
+ "skillsUnknownCommand": "Comando desconhecido: {cmd}\n Uso: opensquad skills list|install|remove|update",
48
+ "chooseSkills": "Quais skills você quer instalar? (opcional)",
49
+ "skillsEnvWarning": " Requer: {vars}",
50
+ "skillsSkipped": "Você pode instalar skills depois com: npx @julioventura/opensquad install <nome>",
51
+ "skillsInstalledCount": "{count} skill(s) instalada(s).",
52
+ "agentsNotInitialized": "Instalação Opensquad não encontrada. Execute 'init' primeiro.",
53
+ "agentsInstalledHeader": "Instalados:",
54
+ "agentsNoneInstalled": "Nenhum agent instalado ainda.",
55
+ "agentsInstallHint": "Instale com: npx @julioventura/opensquad agents install <id>",
56
+ "agentsInstalling": "Instalando {id}...",
57
+ "agentsInstalled": "✅ Instalado: {id}",
58
+ "agentsAlreadyInstalled": "⚠️ {id} já está instalado. Reinstalar? (s/n) ",
59
+ "agentsReinstalled": "✅ Reinstalado: {id}",
60
+ "agentsRemoving": "Removendo {id}...",
61
+ "agentsRemoved": "✅ Removido: {id}",
62
+ "agentsNotInstalled": "⚠️ {id} não está instalado.",
63
+ "agentsUpdating": "Atualizando todos os agents instalados...",
64
+ "agentsUpdateDone": "✅ {count} agent(s) atualizado(s).",
65
+ "agentsUpdateNone": "Nenhum agent instalado para atualizar.",
66
+ "agentsError": "❌ Erro: {message}",
67
+ "agentsUnknownCommand": "Comando desconhecido: {cmd}\n Uso: opensquad agents list|install|remove|update",
68
+ "step1VsCodeCopilot": "1. Abra este diretório no VS Code",
69
+ "step2VsCodeCopilot": "2. Abra o Copilot Chat (Ctrl+Alt+I)",
70
+ "step3VsCodeCopilot": "3. Digite /opensquad para começar",
71
+ "step1QwenCode": "1. Abra este diretório no Qwen Code",
72
+ "step2QwenCode": "2. Digite /opensquad para começar",
73
+ "step1GeminiCli": "1. Abra este diretório no Gemini CLI",
74
+ "step2GeminiCli": "2. Digite /opensquad para começar",
75
+ "step1Trae": "1. Abra este projeto no Trae",
76
+ "step2Trae": "2. Digite /opensquad no chat para começar",
77
+ "tokenCostWarning": "Executar squads consome tokens de IA (pagos). Monitore seu consumo na sua IDE ou no dashboard do provedor de IA."
78
+ }
package/src/logger.js ADDED
@@ -0,0 +1,38 @@
1
+ import { appendFile, mkdir, readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+
4
+ export async function logEvent(action, details = {}, targetDir = process.cwd()) {
5
+ try {
6
+ const logDir = join(targetDir, '_opensquad', 'logs');
7
+ await mkdir(logDir, { recursive: true });
8
+ const entry = JSON.stringify({
9
+ timestamp: new Date().toISOString(),
10
+ action,
11
+ details,
12
+ });
13
+ await appendFile(join(logDir, 'cli.log'), entry + '\n', 'utf-8');
14
+ } catch {
15
+ // Silent — logging must never break the operation
16
+ }
17
+ }
18
+
19
+ export async function readCliLogs({ action, limit } = {}, targetDir = process.cwd()) {
20
+ try {
21
+ const raw = await readFile(join(targetDir, '_opensquad', 'logs', 'cli.log'), 'utf-8');
22
+ const lines = raw.trim().split('\n');
23
+ let entries = [];
24
+ for (const line of lines) {
25
+ try {
26
+ entries.push(JSON.parse(line));
27
+ } catch {
28
+ // Skip malformed lines
29
+ }
30
+ }
31
+ entries.reverse(); // newest first
32
+ if (action) entries = entries.filter((e) => e.action === action);
33
+ if (limit) entries = entries.slice(0, limit);
34
+ return entries;
35
+ } catch {
36
+ return [];
37
+ }
38
+ }
package/src/prompt.js ADDED
@@ -0,0 +1,46 @@
1
+ import { t } from './i18n.js';
2
+
3
+ export function createPrompt() {
4
+ return {
5
+ async ask(question) {
6
+ const { default: input } = await import('@inquirer/input');
7
+ return input({ message: question });
8
+ },
9
+ async choose(question, options) {
10
+ const { default: select } = await import('@inquirer/select');
11
+
12
+ const choices = options.map(opt => ({
13
+ name: opt.label,
14
+ value: opt,
15
+ }));
16
+
17
+ return select({
18
+ message: ` ${question}`,
19
+ choices,
20
+ loop: false,
21
+ });
22
+ },
23
+ async multiChoose(question, options, { validate } = {}) {
24
+ const { default: checkbox, Separator } = await import('@inquirer/checkbox');
25
+
26
+ const choices = options.map(opt => {
27
+ if (opt.separator) return new Separator(opt.label);
28
+ return {
29
+ name: opt.label,
30
+ value: opt.value,
31
+ checked: opt.checked ?? false,
32
+ disabled: opt.disabled ? t('comingSoon') : false,
33
+ };
34
+ });
35
+
36
+ return checkbox({
37
+ message: ` ${question}`,
38
+ choices,
39
+ loop: false,
40
+ validate: validate ?? ((selected) =>
41
+ selected.length > 0 || t('atLeastOneIde')),
42
+ });
43
+ },
44
+ close() {},
45
+ };
46
+ }
@@ -0,0 +1,146 @@
1
+ # Opensquad
2
+
3
+ Crie squads de agentes de IA que trabalham juntos — direto do seu IDE.
4
+
5
+ ## Como Usar
6
+
7
+ Abra esta pasta no seu IDE e digite:
8
+
9
+ ```
10
+ /opensquad
11
+ ```
12
+
13
+ Isso abre o menu principal. De lá você pode criar squads, executá-los e mais.
14
+
15
+ Você também pode ser direto — descreva o que quer em linguagem natural:
16
+
17
+ ```
18
+ /opensquad crie um squad para escrever posts no LinkedIn sobre IA
19
+ /opensquad execute o squad meu-squad
20
+ ```
21
+
22
+ ## Criar um Squad
23
+
24
+ Digite `/opensquad` e escolha "Criar squad" no menu, ou seja direto:
25
+
26
+ ```
27
+ /opensquad crie um squad para [o que você precisa]
28
+ ```
29
+
30
+ O Arquiteto fará algumas perguntas, projetará o squad e configurará tudo automaticamente.
31
+
32
+ ## Executar um Squad
33
+
34
+ Digite `/opensquad` e escolha "Executar squad" no menu, ou seja direto:
35
+
36
+ ```
37
+ /opensquad execute o squad <nome-do-squad>
38
+ ```
39
+
40
+ O squad executa automaticamente, pausando apenas nos checkpoints de decisão.
41
+
42
+ ## Escritório Virtual
43
+
44
+ O Escritório Virtual é uma interface visual 2D que mostra seus agentes trabalhando em tempo real.
45
+
46
+ Ele nao e o mesmo artefato que o relatorio operacional em HTML gerado ao final de cada run.
47
+
48
+ - `opensquad-dashboard-design`: skill de design e evolucao visual do app/dashboard 2D
49
+ - `DASHBOARD 2`: relatorio operacional da run, gerado como `run-dashboard.html` dentro da pasta de output da execucao
50
+
51
+ **Passo 1 — Rode a squad** (no seu IDE):
52
+
53
+ ```text
54
+ /opensquad
55
+ ```
56
+
57
+ Ou execute diretamente:
58
+
59
+ ```text
60
+ /opensquad run <nome-do-squad>
61
+ ```
62
+
63
+ Ao final da pipeline, o runner gera automaticamente o `DASHBOARD 2` com estes arquivos dentro da run:
64
+
65
+ - `squads/<nome-do-squad>/output/<run-id>/run-dashboard.html`
66
+ - `squads/<nome-do-squad>/output/<run-id>/run-dashboard.data.json`
67
+
68
+ Em squads legadas que ainda usam a raiz de `output/`, o HTML pode ficar diretamente em `squads/<nome-do-squad>/output/run-dashboard.html`.
69
+
70
+ **Passo 2 — Abra localmente**:
71
+
72
+ - direto no navegador pelo arquivo `run-dashboard.html`; ou
73
+ - sirva a raiz do projeto localmente para navegar por URL HTTP
74
+
75
+ Exemplo no terminal, a partir de `C:\contexto\OPENSQUAD`:
76
+
77
+ ```bash
78
+ npx serve .
79
+ ```
80
+
81
+ **Passo 3 —** Abra a URL local correspondente ao HTML da run, por exemplo:
82
+
83
+ ```text
84
+ http://localhost:3000/squads/<nome-do-squad>/output/<run-id>/run-dashboard.html
85
+ ```
86
+
87
+ ---
88
+
89
+ # Opensquad (English)
90
+
91
+ Create AI squads that work together — right from your IDE.
92
+
93
+ ## How to Use
94
+
95
+ Open this folder in your IDE and type:
96
+
97
+ ```
98
+ /opensquad
99
+ ```
100
+
101
+ This opens the main menu. From there you can create squads, run them, and more.
102
+
103
+ You can also be direct — describe what you want in plain language:
104
+
105
+ ```
106
+ /opensquad create a squad for writing LinkedIn posts about AI
107
+ /opensquad run my-squad
108
+ ```
109
+
110
+ ## Create a Squad
111
+
112
+ Type `/opensquad` and choose "Create squad" from the menu, or be direct:
113
+
114
+ ```
115
+ /opensquad create a squad for [what you need]
116
+ ```
117
+
118
+ The Architect will ask a few questions, design the squad, and set everything up automatically.
119
+
120
+ ## Run a Squad
121
+
122
+ Type `/opensquad` and choose "Run squad" from the menu, or be direct:
123
+
124
+ ```
125
+ /opensquad run the <squad-name> squad
126
+ ```
127
+
128
+ The squad runs automatically, pausing only at decision checkpoints.
129
+
130
+ ## Virtual Office
131
+
132
+ The Virtual Office is a 2D visual interface that shows your agents working in real time.
133
+
134
+ **Step 1 — Generate the dashboard** (in your IDE):
135
+
136
+ ```
137
+ /opensquad dashboard
138
+ ```
139
+
140
+ **Step 2 — Serve it locally** (in terminal):
141
+
142
+ ```bash
143
+ npx serve squads/<squad-name>/dashboard
144
+ ```
145
+
146
+ **Step 3 —** Open `http://localhost:3000` in your browser.
package/src/runs.js ADDED
@@ -0,0 +1,318 @@
1
+ import { readdir, readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+
4
+ const MAX_RUNS = 20;
5
+ const ARCHIVE_DIR_NAME = 'archive';
6
+ const RUN_METADATA_PATHS = {
7
+ editorialPlan: ['editorial-plan.md', 'v1/editorial-plan.md'],
8
+ researchBrief: ['research-brief.md', 'v1/research-brief.md'],
9
+ publishResult: ['publish-result.md', 'v1/publish-result.md'],
10
+ };
11
+
12
+ export async function listRuns(squadName, targetDir = process.cwd(), options = {}) {
13
+ const includeArchived = options.includeArchived || options.archivedOnly;
14
+ const archivedOnly = options.archivedOnly || false;
15
+ const includeMetrics = options.includeMetrics || false;
16
+ const squadsDir = join(targetDir, 'squads');
17
+ let squadNames;
18
+
19
+ try {
20
+ if (squadName) {
21
+ squadNames = [squadName];
22
+ } else {
23
+ const entries = await readdir(squadsDir, { withFileTypes: true });
24
+ squadNames = entries.filter((e) => e.isDirectory()).map((e) => e.name);
25
+ }
26
+ } catch {
27
+ return [];
28
+ }
29
+
30
+ const runs = [];
31
+ const envVars = includeMetrics ? await loadEnvVars(targetDir) : {};
32
+
33
+ for (const name of squadNames) {
34
+ const outputDir = join(squadsDir, name, 'output');
35
+ let runDirs;
36
+ try {
37
+ const entries = await readdir(outputDir, { withFileTypes: true });
38
+ runDirs = entries
39
+ .filter((e) => e.isDirectory() && e.name !== ARCHIVE_DIR_NAME)
40
+ .map((e) => ({ runId: e.name, runPath: join(outputDir, e.name), archived: false }));
41
+
42
+ if (includeArchived) {
43
+ const archiveDir = entries.find((e) => e.isDirectory() && e.name === ARCHIVE_DIR_NAME);
44
+ if (archiveDir) {
45
+ const archivedEntries = await readdir(join(outputDir, ARCHIVE_DIR_NAME), { withFileTypes: true });
46
+ const archivedRuns = archivedEntries
47
+ .filter((e) => e.isDirectory())
48
+ .map((e) => ({
49
+ runId: e.name,
50
+ runPath: join(outputDir, ARCHIVE_DIR_NAME, e.name),
51
+ archived: true,
52
+ }));
53
+ runDirs.push(...archivedRuns);
54
+ }
55
+ }
56
+ } catch {
57
+ continue;
58
+ }
59
+
60
+ if (archivedOnly) {
61
+ runDirs = runDirs.filter((run) => run.archived);
62
+ }
63
+
64
+ for (const { runId, runPath, archived } of runDirs) {
65
+ const run = {
66
+ squad: name,
67
+ runId,
68
+ archived,
69
+ status: 'unknown',
70
+ steps: null,
71
+ duration: null,
72
+ theme: null,
73
+ publishedAt: null,
74
+ instagramPostId: null,
75
+ instagramUrl: null,
76
+ facebookPostId: null,
77
+ facebookUrl: null,
78
+ youtubeVideoId: null,
79
+ youtubeUrl: null,
80
+ youtubeThumbnail: null,
81
+ likes: null,
82
+ views: null,
83
+ viewsLabel: null,
84
+ };
85
+
86
+ try {
87
+ const raw = await readFile(join(runPath, 'state.json'), 'utf-8');
88
+ const state = JSON.parse(raw);
89
+ run.status = state.status || 'unknown';
90
+ if (state.step) run.steps = `${state.step.current}/${state.step.total}`;
91
+ if (state.startedAt && (state.completedAt || state.failedAt)) {
92
+ const start = new Date(state.startedAt).getTime();
93
+ const end = new Date(state.completedAt || state.failedAt).getTime();
94
+ run.duration = formatDuration(end - start);
95
+ }
96
+ } catch {
97
+ // No state.json or malformed — keep defaults
98
+ }
99
+
100
+ await hydrateRunMetadata(run, runPath);
101
+
102
+ if (includeMetrics) {
103
+ await hydrateRunMetrics(run, envVars);
104
+ }
105
+
106
+ runs.push(run);
107
+ }
108
+ }
109
+
110
+ runs.sort((a, b) => b.runId.localeCompare(a.runId));
111
+ return runs.slice(0, MAX_RUNS);
112
+ }
113
+
114
+ async function hydrateRunMetadata(run, runPath) {
115
+ const editorialPlan = await firstExistingFile(runPath, RUN_METADATA_PATHS.editorialPlan);
116
+ const researchBrief = await firstExistingFile(runPath, RUN_METADATA_PATHS.researchBrief);
117
+ const publishResult = await firstExistingFile(runPath, RUN_METADATA_PATHS.publishResult);
118
+
119
+ const themeSource = editorialPlan || researchBrief;
120
+ if (themeSource) {
121
+ run.theme = extractTheme(themeSource);
122
+ }
123
+
124
+ if (publishResult) {
125
+ run.publishedAt = extractLabeledValue(publishResult, 'Publicado em');
126
+ run.instagramPostId = extractLabeledValue(publishResult, 'Instagram Post ID');
127
+ run.instagramUrl = extractLabeledValue(publishResult, 'Instagram URL');
128
+ run.facebookPostId = extractLabeledValue(publishResult, 'Facebook Post ID');
129
+ run.facebookUrl = extractLabeledValue(publishResult, 'Facebook URL');
130
+ run.youtubeVideoId = extractLabeledValue(publishResult, 'YouTube Video ID');
131
+ run.youtubeUrl = extractLabeledValue(publishResult, 'YouTube URL');
132
+ run.youtubeThumbnail = extractLabeledValue(publishResult, 'YouTube Thumbnail');
133
+ const status = extractLabeledValue(publishResult, 'Status');
134
+ if (status) run.status = status.toLowerCase();
135
+ }
136
+ }
137
+
138
+ async function hydrateRunMetrics(run, envVars) {
139
+ const accessToken = envVars.INSTAGRAM_ACCESS_TOKEN;
140
+ if (!accessToken || !run.instagramPostId) return;
141
+
142
+ const media = await fetchJson(
143
+ `https://graph.facebook.com/v22.0/${run.instagramPostId}?fields=like_count&access_token=${encodeURIComponent(accessToken)}`,
144
+ );
145
+
146
+ if (media?.like_count != null) {
147
+ run.likes = media.like_count;
148
+ }
149
+
150
+ const metricsToTry = [
151
+ { metric: 'views', label: 'views' },
152
+ { metric: 'video_views', label: 'views' },
153
+ { metric: 'plays', label: 'views' },
154
+ { metric: 'impressions', label: 'impressions' },
155
+ ];
156
+
157
+ for (const metric of metricsToTry) {
158
+ const insight = await fetchJson(
159
+ `https://graph.facebook.com/v22.0/${run.instagramPostId}/insights?metric=${metric.metric}&access_token=${encodeURIComponent(accessToken)}`,
160
+ );
161
+
162
+ const value = insight?.data?.[0]?.values?.[0]?.value;
163
+ if (value != null) {
164
+ run.views = value;
165
+ run.viewsLabel = metric.label;
166
+ break;
167
+ }
168
+ }
169
+ }
170
+
171
+ async function fetchJson(url) {
172
+ try {
173
+ const response = await fetch(url);
174
+ const data = await response.json();
175
+ if (!response.ok || data?.error) return null;
176
+ return data;
177
+ } catch {
178
+ return null;
179
+ }
180
+ }
181
+
182
+ async function firstExistingFile(runPath, relativePaths) {
183
+ for (const relativePath of relativePaths) {
184
+ try {
185
+ return await readFile(join(runPath, relativePath), 'utf-8');
186
+ } catch {
187
+ // Try next path
188
+ }
189
+ }
190
+
191
+ return null;
192
+ }
193
+
194
+ function extractTheme(content) {
195
+ const directPatterns = [
196
+ /\*\*Tema Central:\*\*\s*(.+)/i,
197
+ /\*\*Tema central da semana:\*\*\s*(.+)/i,
198
+ ];
199
+
200
+ for (const pattern of directPatterns) {
201
+ const match = content.match(pattern);
202
+ if (match) return sanitizeValue(match[1]);
203
+ }
204
+
205
+ const lines = content.split(/\r?\n/);
206
+ const headingIndex = lines.findIndex((line) => /^##\s+Tema Central da Semana/i.test(line.trim()));
207
+ if (headingIndex !== -1) {
208
+ for (let index = headingIndex + 1; index < lines.length; index += 1) {
209
+ const candidate = sanitizeValue(lines[index]);
210
+ if (candidate) return candidate;
211
+ }
212
+ }
213
+
214
+ return null;
215
+ }
216
+
217
+ function extractLabeledValue(content, label) {
218
+ const escapedLabel = label.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
219
+ const match = content.match(new RegExp(`\\*\\*${escapedLabel}:\\*\\*\\s*(.+)`, 'i'));
220
+ return match ? sanitizeValue(match[1]) : null;
221
+ }
222
+
223
+ function sanitizeValue(value) {
224
+ if (!value) return null;
225
+ return value
226
+ .replace(/^\*\*|\*\*$/g, '')
227
+ .replace(/^__|__$/g, '')
228
+ .replace(/^`|`$/g, '')
229
+ .replace(/^<|>$/g, '')
230
+ .trim() || null;
231
+ }
232
+
233
+ async function loadEnvVars(targetDir) {
234
+ const envVars = { ...process.env };
235
+
236
+ try {
237
+ const raw = await readFile(join(targetDir, '.env'), 'utf-8');
238
+ for (const line of raw.split(/\r?\n/)) {
239
+ const trimmed = line.trim();
240
+ if (!trimmed || trimmed.startsWith('#')) continue;
241
+ const separatorIndex = trimmed.indexOf('=');
242
+ if (separatorIndex === -1) continue;
243
+ const key = trimmed.slice(0, separatorIndex).trim();
244
+ const value = trimmed.slice(separatorIndex + 1).trim().replace(/^['"]|['"]$/g, '');
245
+ if (key && !(key in envVars)) {
246
+ envVars[key] = value;
247
+ }
248
+ }
249
+ } catch {
250
+ // Optional .env
251
+ }
252
+
253
+ return envVars;
254
+ }
255
+
256
+ export function formatDuration(ms) {
257
+ if (ms <= 0) return '0s';
258
+ const seconds = Math.floor(ms / 1000);
259
+ const hours = Math.floor(seconds / 3600);
260
+ const minutes = Math.floor((seconds % 3600) / 60);
261
+ const secs = seconds % 60;
262
+
263
+ if (hours > 0) return `${hours}h ${minutes}m`;
264
+ if (minutes > 0) return `${minutes}m ${secs}s`;
265
+ return `${secs}s`;
266
+ }
267
+
268
+ export function printRuns(runs) {
269
+ const options = arguments[1] || {};
270
+ if (runs.length === 0) {
271
+ console.log('\n No runs found.\n');
272
+ return;
273
+ }
274
+
275
+ let currentSquad = null;
276
+ for (const run of runs) {
277
+ if (run.squad !== currentSquad) {
278
+ currentSquad = run.squad;
279
+ console.log(`\n ${currentSquad}`);
280
+ console.log(' ' + '─'.repeat(50));
281
+ }
282
+ const parts = [` ${run.runId}`];
283
+ if (run.archived) parts.push('[archived]');
284
+ parts.push(`[${run.status}]`);
285
+ if (run.steps) parts.push(`${run.steps} steps`);
286
+ if (run.duration) parts.push(run.duration);
287
+ console.log(parts.join(' '));
288
+
289
+ if (options.showDetails) {
290
+ const detailParts = [];
291
+ if (run.theme) detailParts.push(`tema: ${truncate(run.theme, 90)}`);
292
+ if (run.publishedAt) detailParts.push(`publicado: ${run.publishedAt}`);
293
+ if (detailParts.length > 0) {
294
+ console.log(` ${detailParts.join(' | ')}`);
295
+ }
296
+ }
297
+
298
+ if (options.showMetrics) {
299
+ const metricParts = [];
300
+ if (run.instagramUrl) metricParts.push(run.instagramUrl);
301
+ else if (run.youtubeUrl) metricParts.push(run.youtubeUrl);
302
+
303
+ const likes = run.likes != null ? run.likes : 'n/a';
304
+ const views = run.views != null ? run.views : 'n/a';
305
+ const viewsLabel = run.viewsLabel || 'views';
306
+ metricParts.push(`likes: ${likes}`);
307
+ metricParts.push(`${viewsLabel}: ${views}`);
308
+
309
+ console.log(` ${metricParts.join(' | ')}`);
310
+ }
311
+ }
312
+ console.log();
313
+ }
314
+
315
+ function truncate(value, maxLength) {
316
+ if (!value || value.length <= maxLength) return value;
317
+ return `${value.slice(0, maxLength - 1)}...`;
318
+ }