conectese 0.1.14

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 (260) hide show
  1. package/README.md +265 -0
  2. package/_conectese/.conectese-version +1 -0
  3. package/_conectese/config/playwright.config.json +11 -0
  4. package/_conectese/core/architect.agent.yaml +110 -0
  5. package/_conectese/core/best-practices/_catalog.yaml +116 -0
  6. package/_conectese/core/best-practices/blog-post.md +132 -0
  7. package/_conectese/core/best-practices/blog-seo.md +127 -0
  8. package/_conectese/core/best-practices/copywriting.md +426 -0
  9. package/_conectese/core/best-practices/data-analysis.md +401 -0
  10. package/_conectese/core/best-practices/email-newsletter.md +118 -0
  11. package/_conectese/core/best-practices/email-sales.md +110 -0
  12. package/_conectese/core/best-practices/image-design.md +348 -0
  13. package/_conectese/core/best-practices/instagram-feed.md +235 -0
  14. package/_conectese/core/best-practices/instagram-reels.md +112 -0
  15. package/_conectese/core/best-practices/instagram-stories.md +107 -0
  16. package/_conectese/core/best-practices/linkedin-article.md +116 -0
  17. package/_conectese/core/best-practices/linkedin-post.md +121 -0
  18. package/_conectese/core/best-practices/researching.md +349 -0
  19. package/_conectese/core/best-practices/review.md +269 -0
  20. package/_conectese/core/best-practices/social-networks-publishing.md +294 -0
  21. package/_conectese/core/best-practices/strategist.md +344 -0
  22. package/_conectese/core/best-practices/technical-writing.md +365 -0
  23. package/_conectese/core/best-practices/twitter-post.md +105 -0
  24. package/_conectese/core/best-practices/twitter-thread.md +122 -0
  25. package/_conectese/core/best-practices/whatsapp-broadcast.md +107 -0
  26. package/_conectese/core/best-practices/youtube-script.md +122 -0
  27. package/_conectese/core/best-practices/youtube-shorts.md +112 -0
  28. package/_conectese/core/prompts/build.prompt.md +547 -0
  29. package/_conectese/core/prompts/design.prompt.md +469 -0
  30. package/_conectese/core/prompts/discovery.prompt.md +269 -0
  31. package/_conectese/core/prompts/sherlock-instagram.md +123 -0
  32. package/_conectese/core/prompts/sherlock-linkedin.md +73 -0
  33. package/_conectese/core/prompts/sherlock-shared.md +684 -0
  34. package/_conectese/core/prompts/sherlock-twitter.md +78 -0
  35. package/_conectese/core/prompts/sherlock-youtube.md +85 -0
  36. package/_conectese/core/runner.pipeline.md +535 -0
  37. package/_conectese/core/skills.engine.md +381 -0
  38. package/agents/data-extractor/AGENT.md +13 -0
  39. package/agents/direito-adaneiro/AGENT.md +18 -0
  40. package/agents/direito-administrativo/AGENT.md +18 -0
  41. package/agents/direito-aeroporta-rio/AGENT.md +18 -0
  42. package/agents/direito-agra-rio/AGENT.md +18 -0
  43. package/agents/direito-ambiental/AGENT.md +18 -0
  44. package/agents/direito-banca-rio/AGENT.md +18 -0
  45. package/agents/direito-civil/AGENT.md +18 -0
  46. package/agents/direito-constitcional/AGENT.md +18 -0
  47. package/agents/direito-da-crianc-a-e-do-adolescente-eca/AGENT.md +18 -0
  48. package/agents/direito-da-propriedade-intelectal/AGENT.md +18 -0
  49. package/agents/direito-de-ami-lia/AGENT.md +18 -0
  50. package/agents/direito-de-tra-nsito/AGENT.md +18 -0
  51. package/agents/direito-desportivo/AGENT.md +18 -0
  52. package/agents/direito-digital/AGENT.md +18 -0
  53. package/agents/direito-do-consmidor/AGENT.md +18 -0
  54. package/agents/direito-do-trabalho/AGENT.md +18 -0
  55. package/agents/direito-econo-mico/AGENT.md +18 -0
  56. package/agents/direito-eleitoral/AGENT.md +18 -0
  57. package/agents/direito-empresarial/AGENT.md +18 -0
  58. package/agents/direito-imobilia-rio/AGENT.md +18 -0
  59. package/agents/direito-inanceiro/AGENT.md +18 -0
  60. package/agents/direito-internacional/AGENT.md +18 -0
  61. package/agents/direito-mari-timo/AGENT.md +18 -0
  62. package/agents/direito-me-dico-e-da-sa-de/AGENT.md +18 -0
  63. package/agents/direito-militar/AGENT.md +18 -0
  64. package/agents/direito-ndia-rio/AGENT.md +18 -0
  65. package/agents/direito-notarial-e-registral/AGENT.md +18 -0
  66. package/agents/direito-penal/AGENT.md +18 -0
  67. package/agents/direito-previdencia-rio/AGENT.md +18 -0
  68. package/agents/direito-processal-civil/AGENT.md +18 -0
  69. package/agents/direito-processal-do-trabalho/AGENT.md +18 -0
  70. package/agents/direito-processal-militar/AGENT.md +18 -0
  71. package/agents/direito-processal-penal/AGENT.md +18 -0
  72. package/agents/direito-rbani-stico/AGENT.md +18 -0
  73. package/agents/direito-secrita-rio/AGENT.md +18 -0
  74. package/agents/direito-sindical/AGENT.md +18 -0
  75. package/agents/direito-societa-rio/AGENT.md +18 -0
  76. package/agents/direito-tribta-rio/AGENT.md +18 -0
  77. package/agents/direitos-hmanos/AGENT.md +18 -0
  78. package/agents/legal-analyst/AGENT.md +16 -0
  79. package/agents/legal-synthesizer/AGENT.md +13 -0
  80. package/agents/lgpd-anonymizer/AGENT.md +14 -0
  81. package/agents/lgpd-restorer/AGENT.md +14 -0
  82. package/agents/task-router/AGENT.md +13 -0
  83. package/bin/conectese.js +73 -0
  84. package/dashboard/index.html +12 -0
  85. package/dashboard/package-lock.json +1971 -0
  86. package/dashboard/package.json +28 -0
  87. package/dashboard/public/assets/avatars/Female1_1wave.png +0 -0
  88. package/dashboard/public/assets/avatars/Female1_2wave.png +0 -0
  89. package/dashboard/public/assets/avatars/Female1_blink.png +0 -0
  90. package/dashboard/public/assets/avatars/Female1_talk.png +0 -0
  91. package/dashboard/public/assets/avatars/Female2_1wave.png +0 -0
  92. package/dashboard/public/assets/avatars/Female2_2wave.png +0 -0
  93. package/dashboard/public/assets/avatars/Female2_blink.png +0 -0
  94. package/dashboard/public/assets/avatars/Female2_talk.png +0 -0
  95. package/dashboard/public/assets/avatars/Female3_blink.png +0 -0
  96. package/dashboard/public/assets/avatars/Female3_talk.png +0 -0
  97. package/dashboard/public/assets/avatars/Female3_wave.png +0 -0
  98. package/dashboard/public/assets/avatars/Female4_blink.png +0 -0
  99. package/dashboard/public/assets/avatars/Female4_talk.png +0 -0
  100. package/dashboard/public/assets/avatars/Female4_wave.png +0 -0
  101. package/dashboard/public/assets/avatars/Female5_blink.png +0 -0
  102. package/dashboard/public/assets/avatars/Female5_talk.png +0 -0
  103. package/dashboard/public/assets/avatars/Female5_wave.png +0 -0
  104. package/dashboard/public/assets/avatars/Female6_blink.png +0 -0
  105. package/dashboard/public/assets/avatars/Female6_talk.png +0 -0
  106. package/dashboard/public/assets/avatars/Female6_wave.png +0 -0
  107. package/dashboard/public/assets/avatars/Male1_1wave.png +0 -0
  108. package/dashboard/public/assets/avatars/Male1_2wave.png +0 -0
  109. package/dashboard/public/assets/avatars/Male1_blink.png +0 -0
  110. package/dashboard/public/assets/avatars/Male1_talk.png +0 -0
  111. package/dashboard/public/assets/avatars/Male2_1wave.png +0 -0
  112. package/dashboard/public/assets/avatars/Male2_2wave.png +0 -0
  113. package/dashboard/public/assets/avatars/Male2_blink.png +0 -0
  114. package/dashboard/public/assets/avatars/Male2_talk.png +0 -0
  115. package/dashboard/public/assets/avatars/Male3_blink.png +0 -0
  116. package/dashboard/public/assets/avatars/Male3_talk.png +0 -0
  117. package/dashboard/public/assets/avatars/Male3_wave.png +0 -0
  118. package/dashboard/public/assets/avatars/Male4_blink.png +0 -0
  119. package/dashboard/public/assets/avatars/Male4_talk.png +0 -0
  120. package/dashboard/public/assets/avatars/Male4_wave.png +0 -0
  121. package/dashboard/public/assets/desks/desktop_set_black_down.png +0 -0
  122. package/dashboard/public/assets/desks/desktop_set_black_down_coding-1.png +0 -0
  123. package/dashboard/public/assets/desks/desktop_set_black_down_coding.png +0 -0
  124. package/dashboard/public/assets/desks/desktop_set_black_up.png +0 -0
  125. package/dashboard/public/assets/desks/desktop_set_white_down.png +0 -0
  126. package/dashboard/public/assets/desks/desktop_set_white_down_coding-1.png +0 -0
  127. package/dashboard/public/assets/desks/desktop_set_white_down_coding.png +0 -0
  128. package/dashboard/public/assets/desks/desktop_set_white_up.png +0 -0
  129. package/dashboard/public/assets/furniture/armchair_tan.png +0 -0
  130. package/dashboard/public/assets/furniture/armchair_tan_down.png +0 -0
  131. package/dashboard/public/assets/furniture/backpack_blue.png +0 -0
  132. package/dashboard/public/assets/furniture/backpack_red.png +0 -0
  133. package/dashboard/public/assets/furniture/blinds.png +0 -0
  134. package/dashboard/public/assets/furniture/blinds_large_closed_white.png +0 -0
  135. package/dashboard/public/assets/furniture/bookshelf.png +0 -0
  136. package/dashboard/public/assets/furniture/bookshelf_purple_tall.png +0 -0
  137. package/dashboard/public/assets/furniture/bulletin_board.png +0 -0
  138. package/dashboard/public/assets/furniture/clock.png +0 -0
  139. package/dashboard/public/assets/furniture/coffee_mug.png +0 -0
  140. package/dashboard/public/assets/furniture/coffee_mug_blue.png +0 -0
  141. package/dashboard/public/assets/furniture/coffee_table.png +0 -0
  142. package/dashboard/public/assets/furniture/coffeepot_right.png +0 -0
  143. package/dashboard/public/assets/furniture/coffeetable_black_horizontal.png +0 -0
  144. package/dashboard/public/assets/furniture/couch.png +0 -0
  145. package/dashboard/public/assets/furniture/couch_tan_down.png +0 -0
  146. package/dashboard/public/assets/furniture/cushion_blue.png +0 -0
  147. package/dashboard/public/assets/furniture/cushion_tan.png +0 -0
  148. package/dashboard/public/assets/furniture/desk_wood.png +0 -0
  149. package/dashboard/public/assets/furniture/fancy_rug.png +0 -0
  150. package/dashboard/public/assets/furniture/fancy_rug_wide.png +0 -0
  151. package/dashboard/public/assets/furniture/flowers1.png +0 -0
  152. package/dashboard/public/assets/furniture/flowers2.png +0 -0
  153. package/dashboard/public/assets/furniture/lamp_tan.png +0 -0
  154. package/dashboard/public/assets/furniture/lantern.png +0 -0
  155. package/dashboard/public/assets/furniture/monstera.png +0 -0
  156. package/dashboard/public/assets/furniture/monstera_small.png +0 -0
  157. package/dashboard/public/assets/furniture/picture_frame.png +0 -0
  158. package/dashboard/public/assets/furniture/plant1.png +0 -0
  159. package/dashboard/public/assets/furniture/plant2.png +0 -0
  160. package/dashboard/public/assets/furniture/plant3.png +0 -0
  161. package/dashboard/public/assets/furniture/plant_poof.png +0 -0
  162. package/dashboard/public/assets/furniture/plant_spindly.png +0 -0
  163. package/dashboard/public/assets/furniture/poster_blue.png +0 -0
  164. package/dashboard/public/assets/furniture/rug.png +0 -0
  165. package/dashboard/public/assets/furniture/succulent_blue.png +0 -0
  166. package/dashboard/public/assets/furniture/succulent_green.png +0 -0
  167. package/dashboard/public/assets/furniture/treasurechest_closed_gold.png +0 -0
  168. package/dashboard/public/assets/furniture/water_cooler_better.png +0 -0
  169. package/dashboard/public/assets/furniture/whiteboard.png +0 -0
  170. package/dashboard/public/assets/furniture/whiteboard_stand_graph.png +0 -0
  171. package/dashboard/public/assets/furniture/window_blinds_open.png +0 -0
  172. package/dashboard/src/App.tsx +46 -0
  173. package/dashboard/src/components/SquadCard.tsx +47 -0
  174. package/dashboard/src/components/SquadSelector.tsx +61 -0
  175. package/dashboard/src/components/StatusBadge.tsx +32 -0
  176. package/dashboard/src/components/StatusBar.tsx +97 -0
  177. package/dashboard/src/hooks/useSquadSocket.ts +135 -0
  178. package/dashboard/src/lib/formatTime.ts +16 -0
  179. package/dashboard/src/lib/normalizeState.ts +25 -0
  180. package/dashboard/src/main.tsx +10 -0
  181. package/dashboard/src/office/AgentSprite.ts +241 -0
  182. package/dashboard/src/office/OfficeScene.ts +153 -0
  183. package/dashboard/src/office/PhaserGame.tsx +80 -0
  184. package/dashboard/src/office/RoomBuilder.ts +190 -0
  185. package/dashboard/src/office/assetKeys.ts +150 -0
  186. package/dashboard/src/office/palette.ts +32 -0
  187. package/dashboard/src/plugin/squadWatcher.ts +233 -0
  188. package/dashboard/src/store/useSquadStore.ts +56 -0
  189. package/dashboard/src/styles/globals.css +36 -0
  190. package/dashboard/src/types/state.ts +63 -0
  191. package/dashboard/src/vite-env.d.ts +1 -0
  192. package/dashboard/test-results/.last-run.json +4 -0
  193. package/dashboard/tsconfig.json +24 -0
  194. package/dashboard/tsconfig.tsbuildinfo +1 -0
  195. package/dashboard/vite.config.ts +13 -0
  196. package/package.json +53 -0
  197. package/skills/README.md +63 -0
  198. package/skills/apify/SKILL.md +55 -0
  199. package/skills/blotato/SKILL.md +63 -0
  200. package/skills/canva/SKILL.md +60 -0
  201. package/skills/conectese-agent-creator/SKILL.md +192 -0
  202. package/skills/conectese-skill-creator/SKILL.md +407 -0
  203. package/skills/conectese-skill-creator/agents/analyzer.md +274 -0
  204. package/skills/conectese-skill-creator/agents/comparator.md +202 -0
  205. package/skills/conectese-skill-creator/agents/grader.md +223 -0
  206. package/skills/conectese-skill-creator/assets/eval_review.html +146 -0
  207. package/skills/conectese-skill-creator/eval-viewer/generate_review.py +471 -0
  208. package/skills/conectese-skill-creator/eval-viewer/viewer.html +1325 -0
  209. package/skills/conectese-skill-creator/references/schemas.md +430 -0
  210. package/skills/conectese-skill-creator/references/skill-format.md +235 -0
  211. package/skills/conectese-skill-creator/scripts/__init__.py +0 -0
  212. package/skills/conectese-skill-creator/scripts/aggregate_benchmark.py +401 -0
  213. package/skills/conectese-skill-creator/scripts/quick_validate.py +103 -0
  214. package/skills/conectese-skill-creator/scripts/run_eval.py +310 -0
  215. package/skills/conectese-skill-creator/scripts/utils.py +47 -0
  216. package/skills/image-ai-generator/SKILL.md +124 -0
  217. package/skills/image-ai-generator/scripts/generate.py +175 -0
  218. package/skills/image-creator/SKILL.md +155 -0
  219. package/skills/image-fetcher/SKILL.md +91 -0
  220. package/skills/instagram-publisher/SKILL.md +119 -0
  221. package/skills/instagram-publisher/scripts/publish.js +165 -0
  222. package/skills/resend/SKILL.md +80 -0
  223. package/skills/template-designer/SKILL.md +201 -0
  224. package/skills/template-designer/base-templates/model-a.html +27 -0
  225. package/skills/template-designer/base-templates/model-b.html +31 -0
  226. package/skills/template-designer/base-templates/model-c.html +42 -0
  227. package/src/agents-cli.js +158 -0
  228. package/src/agents.js +134 -0
  229. package/src/i18n.js +48 -0
  230. package/src/init.js +341 -0
  231. package/src/locales/en.json +73 -0
  232. package/src/locales/es.json +72 -0
  233. package/src/locales/pt-BR.json +72 -0
  234. package/src/logger.js +38 -0
  235. package/src/prompt.js +46 -0
  236. package/src/readme/README.md +119 -0
  237. package/src/runs.js +90 -0
  238. package/src/skills-cli.js +157 -0
  239. package/src/skills.js +146 -0
  240. package/src/update.js +169 -0
  241. package/templates/_conectese/.conectese-version +1 -0
  242. package/templates/_conectese/_investigations/.gitkeep +0 -0
  243. package/templates/ide-templates/antigravity/.agent/rules/conectese.md +55 -0
  244. package/templates/ide-templates/antigravity/.agent/workflows/conectese.md +102 -0
  245. package/templates/ide-templates/claude-code/.claude/skills/conectese/SKILL.md +182 -0
  246. package/templates/ide-templates/claude-code/.mcp.json +8 -0
  247. package/templates/ide-templates/claude-code/CLAUDE.md +43 -0
  248. package/templates/ide-templates/codex/.agents/skills/conectese/SKILL.md +6 -0
  249. package/templates/ide-templates/codex/AGENTS.md +105 -0
  250. package/templates/ide-templates/cursor/.cursor/commands/conectese.md +9 -0
  251. package/templates/ide-templates/cursor/.cursor/mcp.json +8 -0
  252. package/templates/ide-templates/cursor/.cursor/rules/conectese.mdc +48 -0
  253. package/templates/ide-templates/cursor/.cursorignore +3 -0
  254. package/templates/ide-templates/opencode/.opencode/commands/conectese.md +9 -0
  255. package/templates/ide-templates/opencode/AGENTS.md +105 -0
  256. package/templates/ide-templates/vscode-copilot/.github/prompts/conectese.prompt.md +201 -0
  257. package/templates/ide-templates/vscode-copilot/.vscode/mcp.json +8 -0
  258. package/templates/ide-templates/vscode-copilot/.vscode/settings.json +3 -0
  259. package/templates/package.json +8 -0
  260. package/templates/squads/.gitkeep +0 -0
@@ -0,0 +1,119 @@
1
+ # Conectese
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
+ /conectese
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
+ /conectese crie um squad para escrever posts no LinkedIn sobre IA
19
+ /conectese execute o squad meu-squad
20
+ ```
21
+
22
+ ## Criar um Squad
23
+
24
+ Digite `/conectese` e escolha "Criar squad" no menu, ou seja direto:
25
+
26
+ ```
27
+ /conectese 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 `/conectese` e escolha "Executar squad" no menu, ou seja direto:
35
+
36
+ ```
37
+ /conectese 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
+ **Passo 1 — Gere o dashboard** (no seu IDE):
47
+
48
+ ```
49
+ /conectese dashboard
50
+ ```
51
+
52
+ **Passo 2 — Sirva localmente** (no terminal):
53
+
54
+ ```bash
55
+ npx serve squads/<nome-do-squad>/dashboard
56
+ ```
57
+
58
+ **Passo 3 —** Abra `http://localhost:3000` no seu navegador.
59
+
60
+ ---
61
+
62
+ # Conectese (English)
63
+
64
+ Create AI squads that work together — right from your IDE.
65
+
66
+ ## How to Use
67
+
68
+ Open this folder in your IDE and type:
69
+
70
+ ```
71
+ /conectese
72
+ ```
73
+
74
+ This opens the main menu. From there you can create squads, run them, and more.
75
+
76
+ You can also be direct — describe what you want in plain language:
77
+
78
+ ```
79
+ /conectese create a squad for writing LinkedIn posts about AI
80
+ /conectese run my-squad
81
+ ```
82
+
83
+ ## Create a Squad
84
+
85
+ Type `/conectese` and choose "Create squad" from the menu, or be direct:
86
+
87
+ ```
88
+ /conectese create a squad for [what you need]
89
+ ```
90
+
91
+ The Architect will ask a few questions, design the squad, and set everything up automatically.
92
+
93
+ ## Run a Squad
94
+
95
+ Type `/conectese` and choose "Run squad" from the menu, or be direct:
96
+
97
+ ```
98
+ /conectese run the <squad-name> squad
99
+ ```
100
+
101
+ The squad runs automatically, pausing only at decision checkpoints.
102
+
103
+ ## Virtual Office
104
+
105
+ The Virtual Office is a 2D visual interface that shows your agents working in real time.
106
+
107
+ **Step 1 — Generate the dashboard** (in your IDE):
108
+
109
+ ```
110
+ /conectese dashboard
111
+ ```
112
+
113
+ **Step 2 — Serve it locally** (in terminal):
114
+
115
+ ```bash
116
+ npx serve squads/<squad-name>/dashboard
117
+ ```
118
+
119
+ **Step 3 —** Open `http://localhost:3000` in your browser.
package/src/runs.js ADDED
@@ -0,0 +1,90 @@
1
+ import { readdir, readFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+
4
+ const MAX_RUNS = 20;
5
+
6
+ export async function listRuns(squadName, targetDir = process.cwd()) {
7
+ const squadsDir = join(targetDir, 'squads');
8
+ let squadNames;
9
+
10
+ try {
11
+ if (squadName) {
12
+ squadNames = [squadName];
13
+ } else {
14
+ const entries = await readdir(squadsDir, { withFileTypes: true });
15
+ squadNames = entries.filter((e) => e.isDirectory()).map((e) => e.name);
16
+ }
17
+ } catch {
18
+ return [];
19
+ }
20
+
21
+ const runs = [];
22
+
23
+ for (const name of squadNames) {
24
+ const outputDir = join(squadsDir, name, 'output');
25
+ let runDirs;
26
+ try {
27
+ const entries = await readdir(outputDir, { withFileTypes: true });
28
+ runDirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
29
+ } catch {
30
+ continue;
31
+ }
32
+
33
+ for (const runId of runDirs) {
34
+ const run = { squad: name, runId, status: 'unknown', steps: null, duration: null };
35
+
36
+ try {
37
+ const raw = await readFile(join(outputDir, runId, 'state.json'), 'utf-8');
38
+ const state = JSON.parse(raw);
39
+ run.status = state.status || 'unknown';
40
+ if (state.step) run.steps = `${state.step.current}/${state.step.total}`;
41
+ if (state.startedAt && (state.completedAt || state.failedAt)) {
42
+ const start = new Date(state.startedAt).getTime();
43
+ const end = new Date(state.completedAt || state.failedAt).getTime();
44
+ run.duration = formatDuration(end - start);
45
+ }
46
+ } catch {
47
+ // No state.json or malformed — keep defaults
48
+ }
49
+
50
+ runs.push(run);
51
+ }
52
+ }
53
+
54
+ runs.sort((a, b) => b.runId.localeCompare(a.runId));
55
+ return runs.slice(0, MAX_RUNS);
56
+ }
57
+
58
+ export function formatDuration(ms) {
59
+ if (ms <= 0) return '0s';
60
+ const seconds = Math.floor(ms / 1000);
61
+ const hours = Math.floor(seconds / 3600);
62
+ const minutes = Math.floor((seconds % 3600) / 60);
63
+ const secs = seconds % 60;
64
+
65
+ if (hours > 0) return `${hours}h ${minutes}m`;
66
+ if (minutes > 0) return `${minutes}m ${secs}s`;
67
+ return `${secs}s`;
68
+ }
69
+
70
+ export function printRuns(runs) {
71
+ if (runs.length === 0) {
72
+ console.log('\n No runs found.\n');
73
+ return;
74
+ }
75
+
76
+ let currentSquad = null;
77
+ for (const run of runs) {
78
+ if (run.squad !== currentSquad) {
79
+ currentSquad = run.squad;
80
+ console.log(`\n ${currentSquad}`);
81
+ console.log(' ' + '─'.repeat(50));
82
+ }
83
+ const parts = [` ${run.runId}`];
84
+ parts.push(`[${run.status}]`);
85
+ if (run.steps) parts.push(`${run.steps} steps`);
86
+ if (run.duration) parts.push(run.duration);
87
+ console.log(parts.join(' '));
88
+ }
89
+ console.log();
90
+ }
@@ -0,0 +1,157 @@
1
+ import { createInterface } from 'node:readline';
2
+ import { stat } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { listInstalled, installSkill, removeSkill, getSkillMeta, getLocalizedDescription } from './skills.js';
5
+ import { loadLocale, t, getLocaleCode } from './i18n.js';
6
+ import { loadSavedLocale } from './init.js';
7
+ import { logEvent } from './logger.js';
8
+
9
+ async function confirm(question) {
10
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
11
+ return new Promise((resolve) => {
12
+ rl.question(question, (answer) => {
13
+ rl.close();
14
+ resolve(answer.trim().toLowerCase());
15
+ });
16
+ });
17
+ }
18
+
19
+ export async function skillsCli(subcommand, args, targetDir) {
20
+ // Require initialized project
21
+ try {
22
+ await stat(join(targetDir, '_conectese'));
23
+ } catch {
24
+ await loadLocale('English');
25
+ console.log(`\n ${t('skillsNotInitialized')}\n`);
26
+ return { success: false };
27
+ }
28
+
29
+ await loadSavedLocale(targetDir);
30
+
31
+ try {
32
+ if (subcommand === 'list' || !subcommand) {
33
+ await runList(targetDir);
34
+ } else if (subcommand === 'install') {
35
+ const installed = await runInstall(args[0], targetDir);
36
+ if (installed === false) return { success: false };
37
+ } else if (subcommand === 'remove') {
38
+ const removed = await runRemove(args[0], targetDir);
39
+ if (removed === false) return { success: false };
40
+ } else if (subcommand === 'update') {
41
+ await runUpdate(targetDir);
42
+ } else if (subcommand === 'update-one') {
43
+ await runUpdateOne(args[0], targetDir);
44
+ } else {
45
+ console.log(`\n ${t('skillsUnknownCommand', { cmd: subcommand })}\n`);
46
+ return { success: false };
47
+ }
48
+ } catch (err) {
49
+ console.log(`\n ${t('skillsError', { message: err.message })}\n`);
50
+ return { success: false };
51
+ }
52
+
53
+ return { success: true };
54
+ }
55
+
56
+ async function runList(targetDir) {
57
+ console.log(`\n Conectese Skills\n`);
58
+
59
+ const installed = await listInstalled(targetDir);
60
+
61
+ if (installed.length > 0) {
62
+ console.log(` ${t('skillsInstalledHeader')}`);
63
+ for (const id of installed) {
64
+ const meta = await getSkillMeta(id);
65
+ if (meta) {
66
+ const desc = getLocalizedDescription(meta, getLocaleCode());
67
+ const parts = [meta.name];
68
+ if (meta.type) parts.push(`(${meta.type})`);
69
+ parts.push(`- ${desc.split('.')[0]}`);
70
+ console.log(` ${parts.join(' ')}`);
71
+ } else {
72
+ console.log(` ${id}`);
73
+ }
74
+ }
75
+ } else {
76
+ console.log(` ${t('skillsNoneInstalled')}`);
77
+ }
78
+
79
+ console.log(`\n Browse available skills at: https://github.com/renatoasse/conectese/tree/main/skills\n`);
80
+ }
81
+
82
+ async function runInstall(id, targetDir) {
83
+ if (!id) {
84
+ console.log('\n Usage: conectese install <id>\n');
85
+ return false;
86
+ }
87
+
88
+ const installed = await listInstalled(targetDir);
89
+ if (installed.includes(id)) {
90
+ const answer = await confirm(`\n ${t('skillsAlreadyInstalled', { id })}`);
91
+ // Accept 'y' (English) or 's' (Portuguese "sim") as affirmative answers
92
+ if (answer !== 'y' && answer !== 's') return false;
93
+ console.log(` ${t('skillsInstalling', { id })}`);
94
+ await installSkill(id, targetDir);
95
+ console.log(` ${t('skillsReinstalled', { id })}\n`);
96
+ await logEvent('skill:install', { name: id, reinstall: true }, targetDir);
97
+ return;
98
+ }
99
+
100
+ console.log(`\n ${t('skillsInstalling', { id })}`);
101
+ await installSkill(id, targetDir);
102
+ console.log(` ${t('skillsInstalled', { id })}\n`);
103
+ await logEvent('skill:install', { name: id }, targetDir);
104
+ }
105
+
106
+ async function runRemove(id, targetDir) {
107
+ if (!id) {
108
+ console.log('\n Usage: conectese uninstall <id>\n');
109
+ return false;
110
+ }
111
+
112
+ const installed = await listInstalled(targetDir);
113
+ if (!installed.includes(id)) {
114
+ console.log(`\n ${t('skillsNotInstalled', { id })}\n`);
115
+ return;
116
+ }
117
+
118
+ console.log(`\n ${t('skillsRemoving', { id })}`);
119
+ await removeSkill(id, targetDir);
120
+ await logEvent('skill:remove', { name: id }, targetDir);
121
+ console.log(` ${t('skillsRemoved', { id })}\n`);
122
+ }
123
+
124
+ async function runUpdate(targetDir) {
125
+ const installed = await listInstalled(targetDir);
126
+ if (installed.length === 0) {
127
+ console.log(`\n ${t('skillsUpdateNone')}\n`);
128
+ return;
129
+ }
130
+
131
+ console.log(`\n ${t('skillsUpdating')}`);
132
+ for (const id of installed) {
133
+ console.log(` ${t('skillsInstalling', { id })}`);
134
+ await installSkill(id, targetDir);
135
+ console.log(` ${t('skillsInstalled', { id })}`);
136
+ }
137
+ await logEvent('skill:update', { count: installed.length }, targetDir);
138
+ console.log(`\n ${t('skillsUpdateDone', { count: installed.length })}\n`);
139
+ }
140
+
141
+ async function runUpdateOne(id, targetDir) {
142
+ if (!id) {
143
+ console.log('\n Usage: conectese update <name>\n');
144
+ return;
145
+ }
146
+
147
+ const installed = await listInstalled(targetDir);
148
+ if (!installed.includes(id)) {
149
+ console.log(`\n ${t('skillsNotInstalled', { id })}\n`);
150
+ return;
151
+ }
152
+
153
+ console.log(`\n ${t('skillsInstalling', { id })}`);
154
+ await installSkill(id, targetDir);
155
+ await logEvent('skill:update', { name: id }, targetDir);
156
+ console.log(` ${t('skillsInstalled', { id })}\n`);
157
+ }
package/src/skills.js ADDED
@@ -0,0 +1,146 @@
1
+ import { cp, readdir, readFile, rm, stat } from 'node:fs/promises';
2
+ import { dirname, join, resolve, sep } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
+ const BUNDLED_SKILLS_DIR = join(__dirname, '..', 'skills');
7
+
8
+ const metaCache = new Map();
9
+
10
+ export async function listInstalled(targetDir) {
11
+ try {
12
+ const skillsDir = join(targetDir, 'skills');
13
+ const entries = await readdir(skillsDir, { withFileTypes: true });
14
+ return entries
15
+ .filter((e) => e.isDirectory() && e.name !== 'conectese-skill-creator')
16
+ .map((e) => e.name);
17
+ } catch (err) {
18
+ if (err.code === 'ENOENT') return [];
19
+ throw err;
20
+ }
21
+ }
22
+
23
+ export async function listAvailable() {
24
+ try {
25
+ const entries = await readdir(BUNDLED_SKILLS_DIR, { withFileTypes: true });
26
+ return entries.filter((e) => e.isDirectory()).map((e) => e.name);
27
+ } catch {
28
+ return [];
29
+ }
30
+ }
31
+
32
+ export async function getSkillMeta(id) {
33
+ if (metaCache.has(id)) return metaCache.get(id);
34
+ try {
35
+ const raw = await readFile(join(BUNDLED_SKILLS_DIR, id, 'SKILL.md'), 'utf-8');
36
+ const content = raw.replace(/\r\n/g, '\n');
37
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
38
+ if (!fmMatch) return { name: id, description: '', descriptions: {}, type: '', env: [] };
39
+
40
+ const fm = fmMatch[1];
41
+ const name = fm.match(/^name:\s*(.+)$/m)?.[1]?.trim() || id;
42
+ const type = fm.match(/^type:\s*(.+)$/m)?.[1]?.trim() || '';
43
+
44
+ // description may use YAML folded scalar (>)
45
+ let description = '';
46
+ const descBlock = fm.match(/^description:\s*>\s*\n((?:\s{2,}.+\n?)+)/m);
47
+ if (descBlock) {
48
+ description = descBlock[1].replace(/\n\s*/g, ' ').trim();
49
+ } else {
50
+ const descInline = fm.match(/^description:\s*(.+)$/m);
51
+ if (descInline) description = descInline[1].trim();
52
+ }
53
+
54
+ // localized descriptions: description_pt-BR, description_es, etc.
55
+ const descriptions = {};
56
+ for (const code of ['pt-BR', 'es']) {
57
+ const key = `description_${code}`;
58
+ // folded scalar
59
+ const blockMatch = fm.match(new RegExp(`^${key}:\\s*>\\s*\\n((?:\\s{2,}.+\\n?)+)`, 'm'));
60
+ if (blockMatch) {
61
+ descriptions[code] = blockMatch[1].replace(/\n\s*/g, ' ').trim();
62
+ } else {
63
+ // inline
64
+ const inlineMatch = fm.match(new RegExp(`^${key}:\\s*(.+)$`, 'm'));
65
+ if (inlineMatch) descriptions[code] = inlineMatch[1].trim();
66
+ }
67
+ }
68
+
69
+ // env is a YAML list: lines starting with " - "
70
+ const env = [];
71
+ const envSection = fm.match(/^env:\s*\n((?:\s+-\s+.+\n?)+)/m);
72
+ if (envSection) {
73
+ for (const line of envSection[1].split('\n')) {
74
+ const item = line.match(/^\s+-\s+(.+)/);
75
+ if (item) env.push(item[1].trim());
76
+ }
77
+ }
78
+
79
+ const result = { name, description, descriptions, type, env };
80
+ metaCache.set(id, result);
81
+ return result;
82
+ } catch (err) {
83
+ if (err.code === 'ENOENT') {
84
+ metaCache.set(id, null);
85
+ return null;
86
+ }
87
+ throw err;
88
+ }
89
+ }
90
+
91
+ function validateSkillId(id) {
92
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(id)) {
93
+ throw new Error(`Invalid skill id: '${id}'`);
94
+ }
95
+ }
96
+
97
+ export async function installSkill(id, targetDir) {
98
+ validateSkillId(id);
99
+ const srcDir = join(BUNDLED_SKILLS_DIR, id);
100
+ try {
101
+ await stat(srcDir);
102
+ } catch (err) {
103
+ if (err.code === 'ENOENT') throw new Error(`Skill '${id}' not found in registry`, { cause: err });
104
+ throw err;
105
+ }
106
+ const destDir = join(targetDir, 'skills', id);
107
+ const resolvedSrc = resolve(srcDir);
108
+ const resolvedDest = resolve(destDir);
109
+ if (resolvedSrc === resolvedDest || resolvedDest.startsWith(resolvedSrc + sep)) {
110
+ return;
111
+ }
112
+ await cp(srcDir, destDir, { recursive: true });
113
+ metaCache.delete(id);
114
+ }
115
+
116
+ export async function removeSkill(id, targetDir) {
117
+ validateSkillId(id);
118
+ const skillDir = join(targetDir, 'skills', id);
119
+ await rm(skillDir, { recursive: true, force: true });
120
+ metaCache.delete(id);
121
+ }
122
+
123
+ export function clearMetaCache() {
124
+ metaCache.clear();
125
+ }
126
+
127
+ export async function getSkillVersion(id, targetDir) {
128
+ try {
129
+ const skillPath = join(targetDir, 'skills', id, 'SKILL.md');
130
+ const content = await readFile(skillPath, 'utf-8');
131
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
132
+ if (!fmMatch) return null;
133
+ const versionMatch = fmMatch[1].match(/^version:\s*(.+)$/m);
134
+ return versionMatch ? versionMatch[1].trim() : null;
135
+ } catch (err) {
136
+ if (err.code === 'ENOENT') return null;
137
+ throw err;
138
+ }
139
+ }
140
+
141
+ export function getLocalizedDescription(meta, localeCode) {
142
+ if (localeCode && localeCode !== 'en' && meta.descriptions?.[localeCode]) {
143
+ return meta.descriptions[localeCode];
144
+ }
145
+ return meta.description;
146
+ }
package/src/update.js ADDED
@@ -0,0 +1,169 @@
1
+ import { cp, mkdir, readFile, stat } from 'node:fs/promises';
2
+ import { join, dirname, relative } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { loadLocale, t } from './i18n.js';
5
+ import { getTemplateEntries, loadSavedLocale, copyCanonicalSources } from './init.js';
6
+ import { listAvailable as listAvailableSkills, listInstalled as listInstalledSkills, installSkill, getSkillMeta } from './skills.js';
7
+ import { logEvent } from './logger.js';
8
+
9
+ async function loadSavedIdes(targetDir) {
10
+ try {
11
+ const prefsPath = join(targetDir, '_conectese', '_memory', 'preferences.md');
12
+ const content = await readFile(prefsPath, 'utf-8');
13
+ const match = content.match(/\*\*IDEs:\*\*\s*(.+)/);
14
+ if (match) {
15
+ return match[1].trim().split(/,\s*/);
16
+ }
17
+ } catch {
18
+ // No preferences file
19
+ }
20
+ return ['claude-code'];
21
+ }
22
+
23
+ const __dirname = dirname(fileURLToPath(import.meta.url));
24
+ const TEMPLATES_DIR = join(__dirname, '..', 'templates');
25
+
26
+ const PROTECTED_PATHS = [
27
+ '_conectese/_memory',
28
+ 'agents',
29
+ 'squads',
30
+ ];
31
+
32
+ function isProtected(relativePath) {
33
+ const normalized = relativePath.replaceAll('\\', '/');
34
+ return PROTECTED_PATHS.some(
35
+ (p) => normalized === p || normalized.startsWith(p + '/')
36
+ );
37
+ }
38
+
39
+ async function backupIfExists(destPath) {
40
+ try {
41
+ await stat(destPath);
42
+ const backupPath = destPath + '.bak';
43
+ await cp(destPath, backupPath);
44
+ return true;
45
+ } catch {
46
+ return false;
47
+ }
48
+ }
49
+
50
+ export async function update(targetDir) {
51
+ console.log('\n 🔄 Conectese — Update\n');
52
+
53
+ // 1. Check initialized
54
+ try {
55
+ await stat(join(targetDir, '_conectese'));
56
+ } catch {
57
+ await loadLocale('English');
58
+ console.log(` ${t('updateNotInitialized')}`);
59
+ return { success: false };
60
+ }
61
+
62
+ // 2. Load user's locale
63
+ await loadSavedLocale(targetDir);
64
+
65
+ // 3. Read versions
66
+ let currentVersion = null;
67
+ try {
68
+ currentVersion = (
69
+ await readFile(join(targetDir, '_conectese', '.conectese-version'), 'utf-8')
70
+ ).trim();
71
+ } catch {
72
+ // Legacy install — no version file
73
+ }
74
+
75
+ const newVersion = (
76
+ await readFile(join(TEMPLATES_DIR, '_conectese', '.conectese-version'), 'utf-8')
77
+ ).trim();
78
+
79
+ // 4. Announce
80
+ if (currentVersion) {
81
+ console.log(
82
+ ` ${t('updateStarting', { old: `v${currentVersion}`, new: `v${newVersion}` })}`
83
+ );
84
+ } else {
85
+ console.log(` ${t('updateStartingUnknown', { new: `v${newVersion}` })}`);
86
+ }
87
+
88
+ // 5. Copy common templates, skipping protected paths and ide-templates/
89
+ const entries = await getTemplateEntries(TEMPLATES_DIR);
90
+ let count = 0;
91
+
92
+ for (const entry of entries) {
93
+ const relativePath = relative(TEMPLATES_DIR, entry);
94
+ if (isProtected(relativePath)) continue;
95
+ // Skip ide-templates — handled separately below
96
+ if (relativePath.replaceAll('\\', '/').startsWith('ide-templates/')) continue;
97
+
98
+ const destPath = join(targetDir, relativePath);
99
+ await mkdir(dirname(destPath), { recursive: true });
100
+ const backed = await backupIfExists(destPath);
101
+ await cp(entry, destPath);
102
+ const displayPath = relativePath.replaceAll('\\', '/');
103
+ if (backed) {
104
+ console.log(` ${t('updatedFile', { path: displayPath })} (backup: ${displayPath}.bak)`);
105
+ } else {
106
+ console.log(` ${t('updatedFile', { path: displayPath })}`);
107
+ }
108
+ count++;
109
+ }
110
+
111
+ // 6. Copy IDE-specific templates based on saved preferences
112
+ const ides = await loadSavedIdes(targetDir);
113
+ for (const ide of ides) {
114
+ const ideSrcDir = join(TEMPLATES_DIR, 'ide-templates', ide);
115
+ let ideEntries;
116
+ try {
117
+ ideEntries = await getTemplateEntries(ideSrcDir);
118
+ } catch {
119
+ continue; // no template dir for this IDE
120
+ }
121
+ for (const entry of ideEntries) {
122
+ const relPath = relative(ideSrcDir, entry);
123
+ if (isProtected(relPath)) continue;
124
+
125
+ const destPath = join(targetDir, relPath);
126
+ await mkdir(dirname(destPath), { recursive: true });
127
+ const backed = await backupIfExists(destPath);
128
+ await cp(entry, destPath);
129
+ const displayPath = relPath.replaceAll('\\', '/');
130
+ if (backed) {
131
+ console.log(` ${t('updatedFile', { path: displayPath })} (backup: ${displayPath}.bak)`);
132
+ } else {
133
+ console.log(` ${t('updatedFile', { path: displayPath })}`);
134
+ }
135
+ count++;
136
+ }
137
+ }
138
+
139
+ // 6a. Copy canonical sources (core, config, dashboard)
140
+ count += await copyCanonicalSources(targetDir, {
141
+ overwrite: true,
142
+ backupFn: backupIfExists,
143
+ protectedFn: isProtected,
144
+ });
145
+
146
+ // 6b. Install new non-MCP, non-hybrid bundled skills not already present
147
+ const availableSkills = await listAvailableSkills();
148
+ const installedSkills = await listInstalledSkills(targetDir);
149
+ for (const id of availableSkills) {
150
+ if (id === 'conectese-skill-creator') continue;
151
+ if (installedSkills.includes(id)) continue;
152
+ const meta = await getSkillMeta(id);
153
+ if (!meta) continue;
154
+ if (meta.type === 'mcp' || meta.type === 'hybrid') continue;
155
+ await installSkill(id, targetDir);
156
+ console.log(` ${t('createdFile', { path: `skills/${id}/SKILL.md` })}`);
157
+ count++;
158
+ }
159
+
160
+ // 7. Summary
161
+ console.log(`\n ${t('updateFileCount', { count })}`);
162
+ console.log(` ${t('updatePreserved')}`);
163
+ console.log(` ${t('updateSuccess', { version: `v${newVersion}` })}`);
164
+ console.log(`\n ${t('updateLatestHint')}\n`);
165
+
166
+ await logEvent('update', { from: currentVersion || 'unknown', to: newVersion }, targetDir);
167
+
168
+ return { success: true };
169
+ }
@@ -0,0 +1 @@
1
+ 0.1.14
File without changes