invos 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (346) hide show
  1. package/README.md +39 -0
  2. package/bin/invos.js +78 -0
  3. package/kit/.agents/skills/apple/DESCRIPTION.md +2 -0
  4. package/kit/.agents/skills/apple/apple-notes/SKILL.md +90 -0
  5. package/kit/.agents/skills/apple/apple-reminders/SKILL.md +130 -0
  6. package/kit/.agents/skills/audit/SKILL.md +177 -0
  7. package/kit/.agents/skills/design-marca/SKILL.md +92 -0
  8. package/kit/.agents/skills/humanizer/SKILL.md +476 -0
  9. package/kit/.agents/skills/instagram-carrossel/SKILL.md +79 -0
  10. package/kit/.agents/skills/instagram-carrossel/references/fetch-assets.md +77 -0
  11. package/kit/.agents/skills/instagram-carrossel/references/publish.md +48 -0
  12. package/kit/.agents/skills/instagram-carrossel/references/render-png.md +147 -0
  13. package/kit/.agents/skills/instagram-carrossel/scripts/publish.js +165 -0
  14. package/kit/.agents/skills/llm-wiki/SKILL.md +507 -0
  15. package/kit/.agents/skills/onboard/SKILL.md +152 -0
  16. package/kit/.agents/skills/pd-ikigai/SKILL.md +269 -0
  17. package/kit/.agents/skills/popular-web-designs/SKILL.md +214 -0
  18. package/kit/.agents/skills/popular-web-designs/templates/airbnb.md +259 -0
  19. package/kit/.agents/skills/popular-web-designs/templates/airtable.md +102 -0
  20. package/kit/.agents/skills/popular-web-designs/templates/apple.md +326 -0
  21. package/kit/.agents/skills/popular-web-designs/templates/bmw.md +193 -0
  22. package/kit/.agents/skills/popular-web-designs/templates/cal.md +272 -0
  23. package/kit/.agents/skills/popular-web-designs/templates/claude.md +325 -0
  24. package/kit/.agents/skills/popular-web-designs/templates/clay.md +317 -0
  25. package/kit/.agents/skills/popular-web-designs/templates/clickhouse.md +294 -0
  26. package/kit/.agents/skills/popular-web-designs/templates/cohere.md +279 -0
  27. package/kit/.agents/skills/popular-web-designs/templates/coinbase.md +142 -0
  28. package/kit/.agents/skills/popular-web-designs/templates/composio.md +320 -0
  29. package/kit/.agents/skills/popular-web-designs/templates/cursor.md +322 -0
  30. package/kit/.agents/skills/popular-web-designs/templates/elevenlabs.md +278 -0
  31. package/kit/.agents/skills/popular-web-designs/templates/expo.md +294 -0
  32. package/kit/.agents/skills/popular-web-designs/templates/figma.md +233 -0
  33. package/kit/.agents/skills/popular-web-designs/templates/framer.md +259 -0
  34. package/kit/.agents/skills/popular-web-designs/templates/hashicorp.md +291 -0
  35. package/kit/.agents/skills/popular-web-designs/templates/ibm.md +345 -0
  36. package/kit/.agents/skills/popular-web-designs/templates/intercom.md +159 -0
  37. package/kit/.agents/skills/popular-web-designs/templates/kraken.md +138 -0
  38. package/kit/.agents/skills/popular-web-designs/templates/linear.app.md +380 -0
  39. package/kit/.agents/skills/popular-web-designs/templates/lovable.md +311 -0
  40. package/kit/.agents/skills/popular-web-designs/templates/minimax.md +270 -0
  41. package/kit/.agents/skills/popular-web-designs/templates/mintlify.md +339 -0
  42. package/kit/.agents/skills/popular-web-designs/templates/miro.md +121 -0
  43. package/kit/.agents/skills/popular-web-designs/templates/mistral.ai.md +274 -0
  44. package/kit/.agents/skills/popular-web-designs/templates/mongodb.md +279 -0
  45. package/kit/.agents/skills/popular-web-designs/templates/notion.md +322 -0
  46. package/kit/.agents/skills/popular-web-designs/templates/nvidia.md +306 -0
  47. package/kit/.agents/skills/popular-web-designs/templates/ollama.md +280 -0
  48. package/kit/.agents/skills/popular-web-designs/templates/opencode.ai.md +294 -0
  49. package/kit/.agents/skills/popular-web-designs/templates/pinterest.md +243 -0
  50. package/kit/.agents/skills/popular-web-designs/templates/posthog.md +269 -0
  51. package/kit/.agents/skills/popular-web-designs/templates/raycast.md +281 -0
  52. package/kit/.agents/skills/popular-web-designs/templates/replicate.md +274 -0
  53. package/kit/.agents/skills/popular-web-designs/templates/resend.md +316 -0
  54. package/kit/.agents/skills/popular-web-designs/templates/revolut.md +198 -0
  55. package/kit/.agents/skills/popular-web-designs/templates/runwayml.md +257 -0
  56. package/kit/.agents/skills/popular-web-designs/templates/sanity.md +370 -0
  57. package/kit/.agents/skills/popular-web-designs/templates/sentry.md +275 -0
  58. package/kit/.agents/skills/popular-web-designs/templates/spacex.md +207 -0
  59. package/kit/.agents/skills/popular-web-designs/templates/spotify.md +259 -0
  60. package/kit/.agents/skills/popular-web-designs/templates/stripe.md +335 -0
  61. package/kit/.agents/skills/popular-web-designs/templates/supabase.md +268 -0
  62. package/kit/.agents/skills/popular-web-designs/templates/superhuman.md +265 -0
  63. package/kit/.agents/skills/popular-web-designs/templates/together.ai.md +276 -0
  64. package/kit/.agents/skills/popular-web-designs/templates/uber.md +308 -0
  65. package/kit/.agents/skills/popular-web-designs/templates/vercel.md +323 -0
  66. package/kit/.agents/skills/popular-web-designs/templates/voltagent.md +336 -0
  67. package/kit/.agents/skills/popular-web-designs/templates/warp.md +266 -0
  68. package/kit/.agents/skills/popular-web-designs/templates/webflow.md +105 -0
  69. package/kit/.agents/skills/popular-web-designs/templates/wise.md +186 -0
  70. package/kit/.agents/skills/popular-web-designs/templates/x.ai.md +270 -0
  71. package/kit/.agents/skills/popular-web-designs/templates/zapier.md +341 -0
  72. package/kit/.agents/skills/productivity/DESCRIPTION.md +3 -0
  73. package/kit/.agents/skills/productivity/google-workspace/SKILL.md +335 -0
  74. package/kit/.agents/skills/productivity/google-workspace/references/gmail-search-syntax.md +63 -0
  75. package/kit/.agents/skills/productivity/google-workspace/scripts/_hermes_home.py +42 -0
  76. package/kit/.agents/skills/productivity/google-workspace/scripts/google_api.py +1225 -0
  77. package/kit/.agents/skills/productivity/google-workspace/scripts/gws_bridge.py +111 -0
  78. package/kit/.agents/skills/productivity/google-workspace/scripts/setup.py +481 -0
  79. package/kit/.agents/skills/productivity/nano-pdf/SKILL.md +52 -0
  80. package/kit/.agents/skills/productivity/notion/SKILL.md +448 -0
  81. package/kit/.agents/skills/productivity/notion/references/block-types.md +112 -0
  82. package/kit/.agents/skills/productivity/ocr-and-documents/DESCRIPTION.md +3 -0
  83. package/kit/.agents/skills/productivity/ocr-and-documents/SKILL.md +172 -0
  84. package/kit/.agents/skills/productivity/ocr-and-documents/scripts/extract_marker.py +87 -0
  85. package/kit/.agents/skills/productivity/ocr-and-documents/scripts/extract_pymupdf.py +98 -0
  86. package/kit/.agents/skills/productivity/powerpoint/LICENSE.txt +30 -0
  87. package/kit/.agents/skills/productivity/powerpoint/SKILL.md +237 -0
  88. package/kit/.agents/skills/productivity/powerpoint/editing.md +205 -0
  89. package/kit/.agents/skills/productivity/powerpoint/pptxgenjs.md +420 -0
  90. package/kit/.agents/skills/productivity/powerpoint/scripts/__init__.py +0 -0
  91. package/kit/.agents/skills/productivity/powerpoint/scripts/add_slide.py +195 -0
  92. package/kit/.agents/skills/productivity/powerpoint/scripts/clean.py +286 -0
  93. package/kit/.agents/skills/productivity/powerpoint/scripts/office/helpers/__init__.py +0 -0
  94. package/kit/.agents/skills/productivity/powerpoint/scripts/office/helpers/merge_runs.py +199 -0
  95. package/kit/.agents/skills/productivity/powerpoint/scripts/office/helpers/simplify_redlines.py +197 -0
  96. package/kit/.agents/skills/productivity/powerpoint/scripts/office/pack.py +159 -0
  97. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  98. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  99. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  100. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  101. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  102. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  103. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  104. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  105. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  106. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  107. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  108. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  109. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  110. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  111. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  112. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  113. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  114. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  115. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  116. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  117. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  118. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  119. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  120. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  121. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  122. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  123. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  124. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ecma/fourth-edition/opc-contentTypes.xsd +42 -0
  125. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ecma/fourth-edition/opc-coreProperties.xsd +50 -0
  126. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ecma/fourth-edition/opc-digSig.xsd +49 -0
  127. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/ecma/fourth-edition/opc-relationships.xsd +33 -0
  128. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/mce/mc.xsd +75 -0
  129. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
  130. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
  131. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
  132. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
  133. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
  134. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  135. package/kit/.agents/skills/productivity/powerpoint/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
  136. package/kit/.agents/skills/proposta/SKILL.md +159 -0
  137. package/kit/.agents/skills/proposta/references/proposta-avancada.md +17 -0
  138. package/kit/.agents/skills/proposta/references/proposta.html +187 -0
  139. package/kit/.agents/skills/session-checkpoint/SKILL.md +80 -0
  140. package/kit/.agents/skills/session-end/SKILL.md +166 -0
  141. package/kit/.agents/skills/session-start/SKILL.md +149 -0
  142. package/kit/.agents/skills/social-content/SKILL.md +119 -0
  143. package/kit/.agents/skills/stop-slop/CHANGELOG.md +24 -0
  144. package/kit/.agents/skills/stop-slop/LICENSE +21 -0
  145. package/kit/.agents/skills/stop-slop/README.md +62 -0
  146. package/kit/.agents/skills/stop-slop/SKILL.md +68 -0
  147. package/kit/.agents/skills/stop-slop/references/examples.md +59 -0
  148. package/kit/.agents/skills/stop-slop/references/phrases.md +128 -0
  149. package/kit/.agents/skills/stop-slop/references/structures.md +134 -0
  150. package/kit/.agents/squads/advisory-board/README.md +34 -0
  151. package/kit/.agents/squads/advisory-board/agents/board-chair.md +161 -0
  152. package/kit/.agents/squads/advisory-board/agents/brene-brown.md +296 -0
  153. package/kit/.agents/squads/advisory-board/agents/charlie-munger.md +590 -0
  154. package/kit/.agents/squads/advisory-board/agents/derek-sivers.md +268 -0
  155. package/kit/.agents/squads/advisory-board/agents/naval-ravikant.md +251 -0
  156. package/kit/.agents/squads/advisory-board/agents/patrick-lencioni.md +394 -0
  157. package/kit/.agents/squads/advisory-board/agents/peter-thiel.md +269 -0
  158. package/kit/.agents/squads/advisory-board/agents/ray-dalio.md +587 -0
  159. package/kit/.agents/squads/advisory-board/agents/reid-hoffman.md +278 -0
  160. package/kit/.agents/squads/advisory-board/agents/simon-sinek.md +291 -0
  161. package/kit/.agents/squads/advisory-board/agents/yvon-chouinard.md +275 -0
  162. package/kit/.agents/squads/advisory-board/checklists/output-quality.md +73 -0
  163. package/kit/.agents/squads/advisory-board/config/config.yaml +67 -0
  164. package/kit/.agents/squads/advisory-board/data/mental-models-catalog.yaml +178 -0
  165. package/kit/.agents/squads/advisory-board/data/routing-catalog.yaml +89 -0
  166. package/kit/.agents/squads/advisory-board/squad.yaml +50 -0
  167. package/kit/.agents/squads/advisory-board/tasks/convene-board.md +152 -0
  168. package/kit/.agents/squads/advisory-board/tasks/diagnose.md +138 -0
  169. package/kit/.agents/squads/advisory-board/tasks/evaluate-scaling.md +165 -0
  170. package/kit/.agents/squads/advisory-board/tasks/get-founder-counsel.md +169 -0
  171. package/kit/.agents/squads/advisory-board/tasks/resolve-culture-crisis.md +164 -0
  172. package/kit/.agents/squads/advisory-board/tasks/review.md +133 -0
  173. package/kit/.agents/squads/advisory-board/tasks/seek-investment-counsel.md +161 -0
  174. package/kit/.agents/squads/advisory-board/workflows/wf-board-meeting.yaml +115 -0
  175. package/kit/.agents/squads/advisory-board/workflows/wf-decision-framework.yaml +135 -0
  176. package/kit/.agents/squads/brand/README.md +179 -0
  177. package/kit/.agents/squads/brand/agents/alexandra-watkins.md +1869 -0
  178. package/kit/.agents/squads/brand/agents/april-dunford.md +1781 -0
  179. package/kit/.agents/squads/brand/agents/brand-chief.md +600 -0
  180. package/kit/.agents/squads/brand/agents/emily-heyward.md +1685 -0
  181. package/kit/.agents/squads/brand/agents/marty-neumeier.md +1642 -0
  182. package/kit/.agents/squads/brand/agents/michael-johnson.md +1814 -0
  183. package/kit/.agents/squads/brand/agents/sagi-haviv.md +2025 -0
  184. package/kit/.agents/squads/brand/checklists/brand-book-checklist.md +31 -0
  185. package/kit/.agents/squads/brand/checklists/brand-launch-checklist.md +52 -0
  186. package/kit/.agents/squads/brand/checklists/brand-strategy-checklist.md +45 -0
  187. package/kit/.agents/squads/brand/checklists/naming-checklist.md +48 -0
  188. package/kit/.agents/squads/brand/checklists/positioning-checklist.md +48 -0
  189. package/kit/.agents/squads/brand/checklists/smoke-tests.md +180 -0
  190. package/kit/.agents/squads/brand/checklists/visual-identity-checklist.md +61 -0
  191. package/kit/.agents/squads/brand/config.yaml +135 -0
  192. package/kit/.agents/squads/brand/data/brand-archetypes.md +135 -0
  193. package/kit/.agents/squads/brand/data/brand-audit-methodology.md +99 -0
  194. package/kit/.agents/squads/brand/data/brand-pantheon.md +61 -0
  195. package/kit/.agents/squads/brand/data/brand-voice-matrix.md +92 -0
  196. package/kit/.agents/squads/brand/data/color-psychology.md +125 -0
  197. package/kit/.agents/squads/brand/squad.yaml +123 -0
  198. package/kit/.agents/squads/brand/tasks/brand-audit.md +150 -0
  199. package/kit/.agents/squads/brand/tasks/brand-book-creation.md +136 -0
  200. package/kit/.agents/squads/brand/tasks/brand-diagnosis.md +135 -0
  201. package/kit/.agents/squads/brand/tasks/brand-touchpoint-audit.md +100 -0
  202. package/kit/.agents/squads/brand/tasks/coherence-check.md +132 -0
  203. package/kit/.agents/squads/brand/tasks/logo-evaluation.md +103 -0
  204. package/kit/.agents/squads/brand/tasks/movement-architecture.md +136 -0
  205. package/kit/.agents/squads/brand/tasks/naming-exercise.md +134 -0
  206. package/kit/.agents/squads/brand/tasks/positioning-exercise.md +146 -0
  207. package/kit/.agents/squads/brand/tasks/research-references.md +225 -0
  208. package/kit/.agents/squads/brand/tasks/visual-identity-brief.md +134 -0
  209. package/kit/.agents/squads/brand/templates/brand-book-tmpl.md +148 -0
  210. package/kit/.agents/squads/brand/templates/brand-soul-canvas-tmpl.md +80 -0
  211. package/kit/.agents/squads/brand/templates/naming-brief-tmpl.md +83 -0
  212. package/kit/.agents/squads/brand/templates/positioning-canvas-tmpl.md +60 -0
  213. package/kit/.agents/squads/brand/templates/visual-identity-brief-tmpl.md +109 -0
  214. package/kit/.agents/squads/brand/workflows/wf-brand-audit.yaml +148 -0
  215. package/kit/.agents/squads/brand/workflows/wf-brand-from-zero.yaml +229 -0
  216. package/kit/.agents/squads/brand/workflows/wf-brief-to-references.yaml +141 -0
  217. package/kit/.agents/squads/hormozi-squad/README.md +25 -0
  218. package/kit/.agents/squads/hormozi-squad/agents/hormozi-ads.md +159 -0
  219. package/kit/.agents/squads/hormozi-squad/agents/hormozi-advisor.md +178 -0
  220. package/kit/.agents/squads/hormozi-squad/agents/hormozi-audit.md +178 -0
  221. package/kit/.agents/squads/hormozi-squad/agents/hormozi-chief.md +121 -0
  222. package/kit/.agents/squads/hormozi-squad/agents/hormozi-closer.md +179 -0
  223. package/kit/.agents/squads/hormozi-squad/agents/hormozi-content.md +166 -0
  224. package/kit/.agents/squads/hormozi-squad/agents/hormozi-copy.md +152 -0
  225. package/kit/.agents/squads/hormozi-squad/agents/hormozi-hooks.md +177 -0
  226. package/kit/.agents/squads/hormozi-squad/agents/hormozi-launch.md +160 -0
  227. package/kit/.agents/squads/hormozi-squad/agents/hormozi-leads.md +198 -0
  228. package/kit/.agents/squads/hormozi-squad/agents/hormozi-models.md +191 -0
  229. package/kit/.agents/squads/hormozi-squad/agents/hormozi-offers.md +197 -0
  230. package/kit/.agents/squads/hormozi-squad/agents/hormozi-pricing.md +151 -0
  231. package/kit/.agents/squads/hormozi-squad/agents/hormozi-retention.md +166 -0
  232. package/kit/.agents/squads/hormozi-squad/agents/hormozi-scale.md +175 -0
  233. package/kit/.agents/squads/hormozi-squad/agents/hormozi-workshop.md +160 -0
  234. package/kit/.agents/squads/hormozi-squad/checklists/output-quality.md +71 -0
  235. package/kit/.agents/squads/hormozi-squad/config/config.yaml +183 -0
  236. package/kit/.agents/squads/hormozi-squad/data/hormozi-frameworks.yaml +105 -0
  237. package/kit/.agents/squads/hormozi-squad/data/routing-catalog.yaml +94 -0
  238. package/kit/.agents/squads/hormozi-squad/squad.yaml +60 -0
  239. package/kit/.agents/squads/hormozi-squad/tasks/audit-business.md +186 -0
  240. package/kit/.agents/squads/hormozi-squad/tasks/close-sale.md +179 -0
  241. package/kit/.agents/squads/hormozi-squad/tasks/create-hooks.md +159 -0
  242. package/kit/.agents/squads/hormozi-squad/tasks/create-offer.md +178 -0
  243. package/kit/.agents/squads/hormozi-squad/tasks/design-workshop.md +192 -0
  244. package/kit/.agents/squads/hormozi-squad/tasks/diagnose.md +166 -0
  245. package/kit/.agents/squads/hormozi-squad/tasks/generate-leads.md +187 -0
  246. package/kit/.agents/squads/hormozi-squad/tasks/plan-launch.md +179 -0
  247. package/kit/.agents/squads/hormozi-squad/tasks/review.md +133 -0
  248. package/kit/.agents/squads/hormozi-squad/tasks/set-pricing.md +167 -0
  249. package/kit/.agents/squads/hormozi-squad/workflows/wf-business-turnaround.yaml +104 -0
  250. package/kit/.agents/squads/hormozi-squad/workflows/wf-offer-creation.yaml +105 -0
  251. package/kit/.agents/squads/index.md +14 -0
  252. package/kit/.agents/squads/instagram-carrossel/DEPENDENCIES.md +75 -0
  253. package/kit/.agents/squads/instagram-carrossel/README.md +52 -0
  254. package/kit/.agents/squads/instagram-carrossel/RUN.md +115 -0
  255. package/kit/.agents/squads/instagram-carrossel/_memory/memories.md +16 -0
  256. package/kit/.agents/squads/instagram-carrossel/agents/copywriter/tasks/create-slides.md +96 -0
  257. package/kit/.agents/squads/instagram-carrossel/agents/copywriter/tasks/generate-angles.md +111 -0
  258. package/kit/.agents/squads/instagram-carrossel/agents/copywriter/tasks/optimize-copy.md +81 -0
  259. package/kit/.agents/squads/instagram-carrossel/agents/copywriter.custom.md +73 -0
  260. package/kit/.agents/squads/instagram-carrossel/agents/image-designer/tasks/create-slides.md +132 -0
  261. package/kit/.agents/squads/instagram-carrossel/agents/image-designer/tasks/propose-visual-identities.md +89 -0
  262. package/kit/.agents/squads/instagram-carrossel/agents/image-designer/tasks/render-export.md +100 -0
  263. package/kit/.agents/squads/instagram-carrossel/agents/image-designer.custom.md +47 -0
  264. package/kit/.agents/squads/instagram-carrossel/agents/publisher/tasks/validate-publish.md +50 -0
  265. package/kit/.agents/squads/instagram-carrossel/agents/publisher.custom.md +26 -0
  266. package/kit/.agents/squads/instagram-carrossel/agents/researcher/tasks/find-and-rank-news.md +105 -0
  267. package/kit/.agents/squads/instagram-carrossel/agents/researcher.custom.md +46 -0
  268. package/kit/.agents/squads/instagram-carrossel/agents/reviewer/tasks/generate-feedback.md +91 -0
  269. package/kit/.agents/squads/instagram-carrossel/agents/reviewer/tasks/score-content.md +103 -0
  270. package/kit/.agents/squads/instagram-carrossel/agents/reviewer.custom.md +53 -0
  271. package/kit/.agents/squads/instagram-carrossel/output/.gitkeep +0 -0
  272. package/kit/.agents/squads/instagram-carrossel/output/slides/.gitkeep +0 -0
  273. package/kit/.agents/squads/instagram-carrossel/output/slides/rendered/.gitkeep +0 -0
  274. package/kit/.agents/squads/instagram-carrossel/pipeline/data/anti-patterns.md +125 -0
  275. package/kit/.agents/squads/instagram-carrossel/pipeline/data/domain-framework.md +92 -0
  276. package/kit/.agents/squads/instagram-carrossel/pipeline/data/instagram-feed-best-practices.md +235 -0
  277. package/kit/.agents/squads/instagram-carrossel/pipeline/data/output-examples.md +244 -0
  278. package/kit/.agents/squads/instagram-carrossel/pipeline/data/quality-criteria.md +120 -0
  279. package/kit/.agents/squads/instagram-carrossel/pipeline/data/research-brief.md +135 -0
  280. package/kit/.agents/squads/instagram-carrossel/pipeline/data/tone-of-voice.md +32 -0
  281. package/kit/.agents/squads/instagram-carrossel/pipeline/pipeline.yaml +136 -0
  282. package/kit/.agents/squads/instagram-carrossel/pipeline/steps/step-01-input-content.md +38 -0
  283. package/kit/.agents/squads/instagram-carrossel/pipeline/steps/step-02-find-news.md +42 -0
  284. package/kit/.agents/squads/instagram-carrossel/pipeline/steps/step-03-select-story.md +59 -0
  285. package/kit/.agents/squads/instagram-carrossel/pipeline/steps/step-04-generate-angles.md +45 -0
  286. package/kit/.agents/squads/instagram-carrossel/pipeline/steps/step-05-select-angle.md +64 -0
  287. package/kit/.agents/squads/instagram-carrossel/pipeline/steps/step-06-create-copy.md +51 -0
  288. package/kit/.agents/squads/instagram-carrossel/pipeline/steps/step-07-approve-copy.md +52 -0
  289. package/kit/.agents/squads/instagram-carrossel/pipeline/steps/step-08-propose-visuals.md +42 -0
  290. package/kit/.agents/squads/instagram-carrossel/pipeline/steps/step-09-select-visual.md +61 -0
  291. package/kit/.agents/squads/instagram-carrossel/pipeline/steps/step-10-create-slides.md +55 -0
  292. package/kit/.agents/squads/instagram-carrossel/pipeline/steps/step-11-approve-images.md +60 -0
  293. package/kit/.agents/squads/instagram-carrossel/pipeline/steps/step-12-review.md +55 -0
  294. package/kit/.agents/squads/instagram-carrossel/pipeline/steps/step-13-publish.md +79 -0
  295. package/kit/.agents/squads/instagram-carrossel/squad-party.csv +6 -0
  296. package/kit/.agents/squads/instagram-carrossel/squad.yaml +70 -0
  297. package/kit/AGENTS.md +175 -0
  298. package/kit/CLAUDE.md +1 -0
  299. package/kit/COMECE-AQUI.md +207 -0
  300. package/kit/INVOS.json +37 -0
  301. package/kit/MEMORY.md +31 -0
  302. package/kit/README.md +434 -0
  303. package/kit/SECURITY.md +39 -0
  304. package/kit/clientes/README.md +72 -0
  305. package/kit/clientes/_index.md +32 -0
  306. package/kit/clientes/_template/arquivos/.gitkeep +0 -0
  307. package/kit/clientes/_template/contexto.md +21 -0
  308. package/kit/clientes/_template/entregas.md +20 -0
  309. package/kit/clientes/_template/perfil.md +47 -0
  310. package/kit/clientes/_template/propostas/.gitkeep +0 -0
  311. package/kit/conteudo/README.md +12 -0
  312. package/kit/conteudo/_fila.md +12 -0
  313. package/kit/conteudo/carrosseis/.gitkeep +0 -0
  314. package/kit/conteudo/publicados/.gitkeep +0 -0
  315. package/kit/docs/audit-enxugamento-sieve.md +187 -0
  316. package/kit/docs/cli.md +62 -0
  317. package/kit/docs/hotmart-webhook.md +96 -0
  318. package/kit/docs/lab-user.md +35 -0
  319. package/kit/docs/prd-invos-cli.md +264 -0
  320. package/kit/integracoes/README.md +31 -0
  321. package/kit/integracoes/composio/README.md +128 -0
  322. package/kit/integracoes/composio/marketing-tools.md +61 -0
  323. package/kit/marca/README.md +13 -0
  324. package/kit/marca/assets/.gitkeep +0 -0
  325. package/kit/marca/marca.md +57 -0
  326. package/kit/memoria/ativo.md +18 -0
  327. package/kit/memoria/decisoes.md +26 -0
  328. package/kit/memoria/empresa.md +46 -0
  329. package/kit/memoria/historico/README.md +8 -0
  330. package/kit/memoria/insights.md +11 -0
  331. package/kit/memoria/perfil.md +29 -0
  332. package/kit/memoria/projetos.md +27 -0
  333. package/kit/memoria/regras/_TEMPLATE-exemplo.md +15 -0
  334. package/kit/memoria/regras/task-com-dono.md +18 -0
  335. package/kit/scripts/smoke-estado.sh +32 -0
  336. package/kit/scripts/validar.sh +206 -0
  337. package/package.json +43 -0
  338. package/src/commands/doctor.js +104 -0
  339. package/src/commands/init.js +44 -0
  340. package/src/commands/install.js +41 -0
  341. package/src/commands/update.js +113 -0
  342. package/src/lock.js +47 -0
  343. package/src/manifest.js +10 -0
  344. package/src/resolve-kit.js +33 -0
  345. package/src/symlinks.js +78 -0
  346. package/src/utils.js +113 -0
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env python3
2
+ """Bridge between Hermes OAuth token and gws CLI.
3
+
4
+ Refreshes the token if expired, then executes gws with the valid access token.
5
+ """
6
+ import json
7
+ import os
8
+ import subprocess
9
+ import sys
10
+ from datetime import datetime, timezone
11
+ from pathlib import Path
12
+
13
+ # Ensure sibling modules (_hermes_home) are importable when run standalone.
14
+ _SCRIPTS_DIR = str(Path(__file__).resolve().parent)
15
+ if _SCRIPTS_DIR not in sys.path:
16
+ sys.path.insert(0, _SCRIPTS_DIR)
17
+
18
+ from _hermes_home import get_hermes_home
19
+
20
+
21
+ def get_token_path() -> Path:
22
+ return get_hermes_home() / "google_token.json"
23
+
24
+
25
+ def _normalize_authorized_user_payload(payload: dict) -> dict:
26
+ normalized = dict(payload)
27
+ if not normalized.get("type"):
28
+ normalized["type"] = "authorized_user"
29
+ return normalized
30
+
31
+
32
+ def refresh_token(token_data: dict) -> dict:
33
+ """Refresh the access token using the refresh token."""
34
+ import urllib.error
35
+ import urllib.parse
36
+ import urllib.request
37
+
38
+ required_keys = ["client_id", "client_secret", "refresh_token", "token_uri"]
39
+ missing = [k for k in required_keys if k not in token_data]
40
+ if missing:
41
+ print(f"ERROR: google_token.json is missing required fields: {', '.join(missing)}", file=sys.stderr)
42
+ print("Please re-authenticate by running the Google Workspace setup script.", file=sys.stderr)
43
+ sys.exit(1)
44
+
45
+ params = urllib.parse.urlencode({
46
+ "client_id": token_data["client_id"],
47
+ "client_secret": token_data["client_secret"],
48
+ "refresh_token": token_data["refresh_token"],
49
+ "grant_type": "refresh_token",
50
+ }).encode()
51
+
52
+ req = urllib.request.Request(token_data["token_uri"], data=params)
53
+ try:
54
+ with urllib.request.urlopen(req, timeout=15) as resp:
55
+ result = json.loads(resp.read())
56
+ except urllib.error.HTTPError as e:
57
+ body = e.read().decode("utf-8", errors="replace")
58
+ print(f"ERROR: Token refresh failed (HTTP {e.code}): {body}", file=sys.stderr)
59
+ print("Re-run setup.py to re-authenticate.", file=sys.stderr)
60
+ sys.exit(1)
61
+ except (urllib.error.URLError, TimeoutError) as e:
62
+ print(f"ERROR: Token refresh failed (network): {e}", file=sys.stderr)
63
+ sys.exit(1)
64
+
65
+ token_data["token"] = result["access_token"]
66
+ token_data["expiry"] = datetime.fromtimestamp(
67
+ datetime.now(timezone.utc).timestamp() + result["expires_in"],
68
+ tz=timezone.utc,
69
+ ).isoformat()
70
+
71
+ get_token_path().write_text(
72
+ json.dumps(_normalize_authorized_user_payload(token_data), indent=2)
73
+ )
74
+ return token_data
75
+
76
+
77
+ def get_valid_token() -> str:
78
+ """Return a valid access token, refreshing if needed."""
79
+ token_path = get_token_path()
80
+ if not token_path.exists():
81
+ print("ERROR: No Google token found. Run setup.py --auth-url first.", file=sys.stderr)
82
+ sys.exit(1)
83
+
84
+ token_data = json.loads(token_path.read_text())
85
+
86
+ expiry = token_data.get("expiry", "")
87
+ if expiry:
88
+ exp_dt = datetime.fromisoformat(expiry.replace("Z", "+00:00"))
89
+ now = datetime.now(timezone.utc)
90
+ if now >= exp_dt:
91
+ token_data = refresh_token(token_data)
92
+
93
+ return token_data["token"]
94
+
95
+
96
+ def main():
97
+ """Refresh token if needed, then exec gws with remaining args."""
98
+ if len(sys.argv) < 2:
99
+ print("Usage: gws_bridge.py <gws args...>", file=sys.stderr)
100
+ sys.exit(1)
101
+
102
+ access_token = get_valid_token()
103
+ env = os.environ.copy()
104
+ env["GOOGLE_WORKSPACE_CLI_TOKEN"] = access_token
105
+
106
+ result = subprocess.run(["gws"] + sys.argv[1:], env=env)
107
+ sys.exit(result.returncode)
108
+
109
+
110
+ if __name__ == "__main__":
111
+ main()
@@ -0,0 +1,481 @@
1
+ #!/usr/bin/env python3
2
+ """Google Workspace OAuth2 setup for Hermes Agent.
3
+
4
+ Fully non-interactive — designed to be driven by the agent via terminal commands.
5
+ The agent mediates between this script and the user (works on CLI, Telegram, Discord, etc.)
6
+
7
+ Commands:
8
+ setup.py --check # Is auth valid? Exit 0 = yes, 1 = no
9
+ setup.py --client-secret /path/to.json # Store OAuth client credentials
10
+ setup.py --auth-url # Print the OAuth URL for user to visit
11
+ setup.py --auth-code CODE # Exchange auth code for token
12
+ setup.py --revoke # Revoke and delete stored token
13
+ setup.py --install-deps # Install Python dependencies only
14
+
15
+ Agent workflow:
16
+ 1. Run --check. If exit 0, auth is good — skip setup.
17
+ 2. Ask user for client_secret.json path. Run --client-secret PATH.
18
+ 3. Run --auth-url. Send the printed URL to the user.
19
+ 4. User opens URL, authorizes, gets redirected to a page with a code.
20
+ 5. User pastes the code. Agent runs --auth-code CODE.
21
+ 6. Run --check to verify. Done.
22
+ """
23
+
24
+ from __future__ import annotations # allow PEP 604 `X | None` on Python 3.9+
25
+
26
+ import argparse
27
+ import json
28
+ import os
29
+ import shutil
30
+ import subprocess
31
+ import sys
32
+ from pathlib import Path
33
+
34
+ # Ensure sibling modules (_hermes_home) are importable when run standalone.
35
+ _SCRIPTS_DIR = str(Path(__file__).resolve().parent)
36
+ if _SCRIPTS_DIR not in sys.path:
37
+ sys.path.insert(0, _SCRIPTS_DIR)
38
+
39
+ from _hermes_home import display_hermes_home, get_hermes_home
40
+
41
+ HERMES_HOME = get_hermes_home()
42
+ TOKEN_PATH = HERMES_HOME / "google_token.json"
43
+ CLIENT_SECRET_PATH = HERMES_HOME / "google_client_secret.json"
44
+ PENDING_AUTH_PATH = HERMES_HOME / "google_oauth_pending.json"
45
+
46
+ SCOPES = [
47
+ "https://www.googleapis.com/auth/gmail.readonly",
48
+ "https://www.googleapis.com/auth/gmail.send",
49
+ "https://www.googleapis.com/auth/gmail.modify",
50
+ "https://www.googleapis.com/auth/calendar",
51
+ "https://www.googleapis.com/auth/drive",
52
+ "https://www.googleapis.com/auth/contacts.readonly",
53
+ "https://www.googleapis.com/auth/spreadsheets",
54
+ "https://www.googleapis.com/auth/documents",
55
+ ]
56
+
57
+ REQUIRED_PACKAGES = ["google-api-python-client", "google-auth-oauthlib", "google-auth-httplib2"]
58
+
59
+ # OAuth redirect for "out of band" manual code copy flow.
60
+ # Google deprecated OOB, so we use a localhost redirect and tell the user to
61
+ # copy the code from the browser's URL bar (or the page body).
62
+ REDIRECT_URI = "http://localhost:1"
63
+
64
+
65
+ def _normalize_authorized_user_payload(payload: dict) -> dict:
66
+ normalized = dict(payload)
67
+ if not normalized.get("type"):
68
+ normalized["type"] = "authorized_user"
69
+ return normalized
70
+
71
+
72
+ def _load_token_payload(path: Path = TOKEN_PATH) -> dict:
73
+ try:
74
+ return json.loads(path.read_text())
75
+ except Exception:
76
+ return {}
77
+
78
+
79
+ def _missing_scopes_from_payload(payload: dict) -> list[str]:
80
+ raw = payload.get("scopes") or payload.get("scope")
81
+ if not raw:
82
+ return []
83
+ granted = {s.strip() for s in (raw.split() if isinstance(raw, str) else raw) if s.strip()}
84
+ return sorted(scope for scope in SCOPES if scope not in granted)
85
+
86
+
87
+ def _format_missing_scopes(missing_scopes: list[str]) -> str:
88
+ bullets = "\n".join(f" - {scope}" for scope in missing_scopes)
89
+ return (
90
+ "Token is valid but missing required Google Workspace scopes:\n"
91
+ f"{bullets}\n"
92
+ "Run the Google Workspace setup again from this same Hermes profile to refresh consent."
93
+ )
94
+
95
+
96
+ def install_deps():
97
+ """Install Google API packages if missing. Returns True on success."""
98
+ try:
99
+ import googleapiclient # noqa: F401
100
+ import google_auth_oauthlib # noqa: F401
101
+ print("Dependencies already installed.")
102
+ return True
103
+ except ImportError:
104
+ pass
105
+
106
+ print("Installing Google API dependencies...")
107
+
108
+ # First choice: pip in the current interpreter. Works for most installs.
109
+ try:
110
+ subprocess.check_call(
111
+ [sys.executable, "-m", "pip", "install", "--quiet"] + REQUIRED_PACKAGES,
112
+ stdout=subprocess.DEVNULL,
113
+ )
114
+ print("Dependencies installed.")
115
+ return True
116
+ except subprocess.CalledProcessError as e:
117
+ pip_error = e
118
+
119
+ # Fallback: the interpreter has no pip (the Hermes Docker image's venv is
120
+ # built with `uv sync`, which does not bootstrap pip). `uv pip install
121
+ # --python <interpreter>` installs into that exact interpreter without
122
+ # needing pip present. Targeting sys.executable keeps us on the venv the
123
+ # script is actually running under, rather than guessing.
124
+ uv = shutil.which("uv")
125
+ if uv:
126
+ try:
127
+ subprocess.check_call(
128
+ [uv, "pip", "install", "--python", sys.executable, "--quiet"]
129
+ + REQUIRED_PACKAGES,
130
+ stdout=subprocess.DEVNULL,
131
+ )
132
+ print("Dependencies installed.")
133
+ return True
134
+ except subprocess.CalledProcessError as e:
135
+ print(f"ERROR: Failed to install dependencies via uv: {e}")
136
+ print(f"Manually: {uv} pip install --python {sys.executable} {' '.join(REQUIRED_PACKAGES)}")
137
+ return False
138
+
139
+ print(f"ERROR: Failed to install dependencies: {pip_error}")
140
+ print(
141
+ "On environments without pip (e.g. Nix, or the Hermes Docker image's "
142
+ "uv-managed venv), install the optional extra instead:"
143
+ )
144
+ print(" pip install 'hermes-agent[google]'")
145
+ print(f"Or manually: {sys.executable} -m pip install {' '.join(REQUIRED_PACKAGES)}")
146
+ return False
147
+
148
+
149
+ def _ensure_deps():
150
+ """Check deps are available, install if not, exit on failure."""
151
+ try:
152
+ import googleapiclient # noqa: F401
153
+ import google_auth_oauthlib # noqa: F401
154
+ except ImportError:
155
+ if not install_deps():
156
+ sys.exit(1)
157
+
158
+
159
+ def check_auth_live():
160
+ """Check auth with a real API call to detect disabled_client/account issues."""
161
+ # quiet=True suppresses the "AUTHENTICATED" print from check_auth so the
162
+ # final status line reflects the live-call outcome (OK or FAILED).
163
+ if not check_auth(quiet=True):
164
+ return False
165
+ try:
166
+ from googleapiclient.discovery import build
167
+ from google.oauth2.credentials import Credentials
168
+ creds = Credentials.from_authorized_user_file(str(TOKEN_PATH))
169
+ service = build("calendar", "v3", credentials=creds)
170
+ service.calendarList().list(maxResults=1).execute()
171
+ print("LIVE_CHECK_OK: Real API call succeeded.")
172
+ return True
173
+ except Exception as e:
174
+ err_str = str(e).lower()
175
+ if "disabled_client" in err_str or "invalid_client" in err_str:
176
+ print(f"LIVE_CHECK_FAILED: OAuth client or account disabled: {e}")
177
+ print(" 1. Check Google Cloud Console for disabled OAuth client")
178
+ print(" 2. Check myaccount.google.com for account status")
179
+ print(" 3. Do NOT retry with a disabled account")
180
+ else:
181
+ print(f"LIVE_CHECK_FAILED: {e}")
182
+ return False
183
+
184
+
185
+ def check_auth(quiet: bool = False):
186
+ """Check if stored credentials are valid. Prints status, exits 0 or 1."""
187
+ if not TOKEN_PATH.exists():
188
+ print(f"NOT_AUTHENTICATED: No token at {TOKEN_PATH}")
189
+ return False
190
+
191
+ _ensure_deps()
192
+ from google.oauth2.credentials import Credentials
193
+ from google.auth.transport.requests import Request
194
+
195
+ try:
196
+ # Don't pass scopes — user may have authorized only a subset.
197
+ # Passing scopes forces google-auth to validate them on refresh,
198
+ # which fails with invalid_scope if the token has fewer scopes
199
+ # than requested.
200
+ creds = Credentials.from_authorized_user_file(str(TOKEN_PATH))
201
+ except Exception as e:
202
+ print(f"TOKEN_CORRUPT: {e}")
203
+ return False
204
+
205
+ payload = _load_token_payload(TOKEN_PATH)
206
+ if creds.valid:
207
+ missing_scopes = _missing_scopes_from_payload(payload)
208
+ if missing_scopes:
209
+ print(f"AUTHENTICATED (partial): Token valid but missing {len(missing_scopes)} scopes:")
210
+ for s in missing_scopes:
211
+ print(f" - {s}")
212
+ if not quiet:
213
+ print(f"AUTHENTICATED: Token valid at {TOKEN_PATH}")
214
+ return True
215
+
216
+ if creds.expired and creds.refresh_token:
217
+ try:
218
+ creds.refresh(Request())
219
+ TOKEN_PATH.write_text(
220
+ json.dumps(
221
+ _normalize_authorized_user_payload(json.loads(creds.to_json())),
222
+ indent=2,
223
+ )
224
+ )
225
+ missing_scopes = _missing_scopes_from_payload(_load_token_payload(TOKEN_PATH))
226
+ if missing_scopes:
227
+ print(f"AUTHENTICATED (partial): Token refreshed but missing {len(missing_scopes)} scopes:")
228
+ for s in missing_scopes:
229
+ print(f" - {s}")
230
+ if not quiet:
231
+ print(f"AUTHENTICATED: Token refreshed at {TOKEN_PATH}")
232
+ return True
233
+ except Exception as e:
234
+ err_str = str(e).lower()
235
+ if "disabled_client" in err_str or "invalid_client" in err_str:
236
+ print(f"OAUTH_CLIENT_DISABLED: {e}")
237
+ print(" The OAuth client or Google account has been disabled.")
238
+ print(" Steps to resolve:")
239
+ print(" 1. Check your Google Cloud Console — verify the OAuth client is not disabled")
240
+ print(" 2. Check if your Google account itself has been disabled at myaccount.google.com")
241
+ print(" 3. If the account is disabled, you can appeal at accounts.google.com/signin/recovery")
242
+ print(" 4. Do NOT retry API calls with a disabled account — this may worsen the situation")
243
+ print(" 5. If the OAuth client is disabled, create a new one in Google Cloud Console")
244
+ elif "token_revoked" in err_str or "invalid_grant" in err_str:
245
+ print(f"TOKEN_REVOKED: {e}")
246
+ print(" Re-run setup to re-authenticate.")
247
+ else:
248
+ print(f"REFRESH_FAILED: {e}")
249
+ return False
250
+
251
+ print("TOKEN_INVALID: Re-run setup.")
252
+ return False
253
+
254
+
255
+ def store_client_secret(path: str):
256
+ """Copy and validate client_secret.json to Hermes home."""
257
+ src = Path(path).expanduser().resolve()
258
+ if not src.exists():
259
+ print(f"ERROR: File not found: {src}")
260
+ sys.exit(1)
261
+
262
+ try:
263
+ data = json.loads(src.read_text())
264
+ except json.JSONDecodeError:
265
+ print("ERROR: File is not valid JSON.")
266
+ sys.exit(1)
267
+
268
+ if "installed" not in data and "web" not in data:
269
+ print("ERROR: Not a Google OAuth client secret file (missing 'installed' key).")
270
+ print("Download the correct file from: https://console.cloud.google.com/apis/credentials")
271
+ sys.exit(1)
272
+
273
+ CLIENT_SECRET_PATH.write_text(json.dumps(data, indent=2))
274
+ print(f"OK: Client secret saved to {CLIENT_SECRET_PATH}")
275
+
276
+
277
+ def _save_pending_auth(*, state: str, code_verifier: str):
278
+ """Persist the OAuth session bits needed for a later token exchange."""
279
+ PENDING_AUTH_PATH.write_text(
280
+ json.dumps(
281
+ {
282
+ "state": state,
283
+ "code_verifier": code_verifier,
284
+ "redirect_uri": REDIRECT_URI,
285
+ },
286
+ indent=2,
287
+ )
288
+ )
289
+
290
+
291
+ def _load_pending_auth() -> dict:
292
+ """Load the pending OAuth session created by get_auth_url()."""
293
+ if not PENDING_AUTH_PATH.exists():
294
+ print("ERROR: No pending OAuth session found. Run --auth-url first.")
295
+ sys.exit(1)
296
+
297
+ try:
298
+ data = json.loads(PENDING_AUTH_PATH.read_text())
299
+ except Exception as e:
300
+ print(f"ERROR: Could not read pending OAuth session: {e}")
301
+ print("Run --auth-url again to start a fresh OAuth session.")
302
+ sys.exit(1)
303
+
304
+ if not data.get("state") or not data.get("code_verifier"):
305
+ print("ERROR: Pending OAuth session is missing PKCE data.")
306
+ print("Run --auth-url again to start a fresh OAuth session.")
307
+ sys.exit(1)
308
+
309
+ return data
310
+
311
+
312
+ def _extract_code_and_state(code_or_url: str) -> tuple[str, str | None]:
313
+ """Accept either a raw auth code or the full redirect URL pasted by the user."""
314
+ if not code_or_url.startswith("http"):
315
+ return code_or_url, None
316
+
317
+ from urllib.parse import parse_qs, urlparse
318
+
319
+ parsed = urlparse(code_or_url)
320
+ params = parse_qs(parsed.query)
321
+ if "code" not in params:
322
+ print("ERROR: No 'code' parameter found in URL.")
323
+ sys.exit(1)
324
+
325
+ state = params.get("state", [None])[0]
326
+ return params["code"][0], state
327
+
328
+
329
+ def get_auth_url():
330
+ """Print the OAuth authorization URL. User visits this in a browser."""
331
+ if not CLIENT_SECRET_PATH.exists():
332
+ print("ERROR: No client secret stored. Run --client-secret first.")
333
+ sys.exit(1)
334
+
335
+ _ensure_deps()
336
+ from google_auth_oauthlib.flow import Flow
337
+
338
+ flow = Flow.from_client_secrets_file(
339
+ str(CLIENT_SECRET_PATH),
340
+ scopes=SCOPES,
341
+ redirect_uri=REDIRECT_URI,
342
+ autogenerate_code_verifier=True,
343
+ )
344
+ auth_url, state = flow.authorization_url(
345
+ access_type="offline",
346
+ prompt="consent",
347
+ )
348
+ _save_pending_auth(state=state, code_verifier=flow.code_verifier)
349
+ # Print just the URL so the agent can extract it cleanly
350
+ print(auth_url)
351
+
352
+
353
+ def exchange_auth_code(code: str):
354
+ """Exchange the authorization code for a token and save it."""
355
+ if not CLIENT_SECRET_PATH.exists():
356
+ print("ERROR: No client secret stored. Run --client-secret first.")
357
+ sys.exit(1)
358
+
359
+ pending_auth = _load_pending_auth()
360
+ raw_callback = code
361
+ code, returned_state = _extract_code_and_state(code)
362
+ if returned_state and returned_state != pending_auth["state"]:
363
+ print("ERROR: OAuth state mismatch. Run --auth-url again to start a fresh session.")
364
+ sys.exit(1)
365
+
366
+ _ensure_deps()
367
+ from google_auth_oauthlib.flow import Flow
368
+ from urllib.parse import parse_qs, urlparse
369
+
370
+ # Extract granted scopes from the callback URL if the user pasted the full redirect URL.
371
+ granted_scopes = list(SCOPES)
372
+ if isinstance(raw_callback, str) and raw_callback.startswith("http"):
373
+ params = parse_qs(urlparse(raw_callback).query)
374
+ scope_val = (params.get("scope") or [""])[0].strip()
375
+ if scope_val:
376
+ granted_scopes = scope_val.split()
377
+
378
+ flow = Flow.from_client_secrets_file(
379
+ str(CLIENT_SECRET_PATH),
380
+ scopes=granted_scopes,
381
+ redirect_uri=pending_auth.get("redirect_uri", REDIRECT_URI),
382
+ state=pending_auth["state"],
383
+ code_verifier=pending_auth["code_verifier"],
384
+ )
385
+
386
+ try:
387
+ # Accept partial scopes — user may deselect some permissions in the consent screen
388
+ os.environ["OAUTHLIB_RELAX_TOKEN_SCOPE"] = "1"
389
+ flow.fetch_token(code=code)
390
+ except Exception as e:
391
+ print(f"ERROR: Token exchange failed: {e}")
392
+ print("The code may have expired. Run --auth-url to get a fresh URL.")
393
+ sys.exit(1)
394
+
395
+ creds = flow.credentials
396
+ token_payload = _normalize_authorized_user_payload(json.loads(creds.to_json()))
397
+
398
+ # Store only the scopes actually granted by the user, not what was requested.
399
+ # creds.to_json() writes the requested scopes, which causes refresh to fail
400
+ # with invalid_scope if the user only authorized a subset.
401
+ actually_granted = list(creds.granted_scopes or []) if hasattr(creds, "granted_scopes") and creds.granted_scopes else []
402
+ if actually_granted:
403
+ token_payload["scopes"] = actually_granted
404
+ elif granted_scopes != SCOPES:
405
+ # granted_scopes was extracted from the callback URL
406
+ token_payload["scopes"] = granted_scopes
407
+
408
+ missing_scopes = _missing_scopes_from_payload(token_payload)
409
+ if missing_scopes:
410
+ print(f"WARNING: Token missing some Google Workspace scopes: {', '.join(missing_scopes)}")
411
+ print("Some services may not be available.")
412
+
413
+ TOKEN_PATH.write_text(json.dumps(token_payload, indent=2))
414
+ PENDING_AUTH_PATH.unlink(missing_ok=True)
415
+ print(f"OK: Authenticated. Token saved to {TOKEN_PATH}")
416
+ print(f"Profile-scoped token location: {display_hermes_home()}/google_token.json")
417
+
418
+
419
+ def revoke():
420
+ """Revoke stored token and delete it."""
421
+ if not TOKEN_PATH.exists():
422
+ print("No token to revoke.")
423
+ return
424
+
425
+ _ensure_deps()
426
+ from google.oauth2.credentials import Credentials
427
+ from google.auth.transport.requests import Request
428
+
429
+ try:
430
+ creds = Credentials.from_authorized_user_file(str(TOKEN_PATH), SCOPES)
431
+ if creds.expired and creds.refresh_token:
432
+ creds.refresh(Request())
433
+
434
+ import urllib.request
435
+ urllib.request.urlopen(
436
+ urllib.request.Request(
437
+ f"https://oauth2.googleapis.com/revoke?token={creds.token}",
438
+ method="POST",
439
+ headers={"Content-Type": "application/x-www-form-urlencoded"},
440
+ ),
441
+ timeout=15,
442
+ )
443
+ print("Token revoked with Google.")
444
+ except Exception as e:
445
+ print(f"Remote revocation failed (token may already be invalid): {e}")
446
+
447
+ TOKEN_PATH.unlink(missing_ok=True)
448
+ PENDING_AUTH_PATH.unlink(missing_ok=True)
449
+ print(f"Deleted {TOKEN_PATH}")
450
+
451
+
452
+ def main():
453
+ parser = argparse.ArgumentParser(description="Google Workspace OAuth setup for Hermes")
454
+ group = parser.add_mutually_exclusive_group(required=True)
455
+ group.add_argument("--check", action="store_true", help="Check if auth is valid (exit 0=yes, 1=no)")
456
+ group.add_argument("--check-live", action="store_true", help="Check auth with a real API call (detects disabled_client)")
457
+ group.add_argument("--client-secret", metavar="PATH", help="Store OAuth client_secret.json")
458
+ group.add_argument("--auth-url", action="store_true", help="Print OAuth URL for user to visit")
459
+ group.add_argument("--auth-code", metavar="CODE", help="Exchange auth code for token")
460
+ group.add_argument("--revoke", action="store_true", help="Revoke and delete stored token")
461
+ group.add_argument("--install-deps", action="store_true", help="Install Python dependencies")
462
+ args = parser.parse_args()
463
+
464
+ if args.check:
465
+ sys.exit(0 if check_auth() else 1)
466
+ if getattr(args, "check_live", False):
467
+ sys.exit(0 if check_auth_live() else 1)
468
+ elif args.client_secret:
469
+ store_client_secret(args.client_secret)
470
+ elif args.auth_url:
471
+ get_auth_url()
472
+ elif args.auth_code:
473
+ exchange_auth_code(args.auth_code)
474
+ elif args.revoke:
475
+ revoke()
476
+ elif args.install_deps:
477
+ sys.exit(0 if install_deps() else 1)
478
+
479
+
480
+ if __name__ == "__main__":
481
+ main()
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: nano-pdf
3
+ description: "Edit PDF text/typos/titles via nano-pdf CLI (NL prompts)."
4
+ version: 1.0.0
5
+ author: community
6
+ license: MIT
7
+ platforms: [linux, macos, windows]
8
+ metadata:
9
+ hermes:
10
+ tags: [PDF, Documents, Editing, NLP, Productivity]
11
+ homepage: https://pypi.org/project/nano-pdf/
12
+ ---
13
+
14
+ # nano-pdf
15
+
16
+ Edit PDFs using natural-language instructions. Point it at a page and describe what to change.
17
+
18
+ ## Prerequisites
19
+
20
+ ```bash
21
+ # Install with uv (recommended — already available in Hermes)
22
+ uv pip install nano-pdf
23
+
24
+ # Or with pip
25
+ pip install nano-pdf
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ ```bash
31
+ nano-pdf edit <file.pdf> <page_number> "<instruction>"
32
+ ```
33
+
34
+ ## Examples
35
+
36
+ ```bash
37
+ # Change a title on page 1
38
+ nano-pdf edit deck.pdf 1 "Change the title to 'Q3 Results' and fix the typo in the subtitle"
39
+
40
+ # Update a date on a specific page
41
+ nano-pdf edit report.pdf 3 "Update the date from January to February 2026"
42
+
43
+ # Fix content
44
+ nano-pdf edit contract.pdf 2 "Change the client name from 'Acme Corp' to 'Acme Industries'"
45
+ ```
46
+
47
+ ## Notes
48
+
49
+ - Page numbers may be 0-based or 1-based depending on version — if the edit hits the wrong page, retry with ±1
50
+ - Always verify the output PDF after editing (use `read_file` to check file size, or open it)
51
+ - The tool uses an LLM under the hood — requires an API key (check `nano-pdf --help` for config)
52
+ - Works well for text changes; complex layout modifications may need a different approach