@jacques-ai/cli 0.0.7-alpha.1

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 (508) hide show
  1. package/dist/assets/mascot-ansi.d.ts +8 -0
  2. package/dist/assets/mascot-ansi.d.ts.map +1 -0
  3. package/dist/assets/mascot-ansi.js +15 -0
  4. package/dist/assets/mascot-ansi.js.map +1 -0
  5. package/dist/cli.d.ts +15 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +53 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/commands/client-helper.d.ts +14 -0
  10. package/dist/commands/client-helper.d.ts.map +1 -0
  11. package/dist/commands/client-helper.js +38 -0
  12. package/dist/commands/client-helper.js.map +1 -0
  13. package/dist/commands/dashboard.d.ts +8 -0
  14. package/dist/commands/dashboard.d.ts.map +1 -0
  15. package/dist/commands/dashboard.js +159 -0
  16. package/dist/commands/dashboard.js.map +1 -0
  17. package/dist/commands/index.d.ts +6 -0
  18. package/dist/commands/index.d.ts.map +1 -0
  19. package/dist/commands/index.js +6 -0
  20. package/dist/commands/index.js.map +1 -0
  21. package/dist/commands/list.d.ts +5 -0
  22. package/dist/commands/list.d.ts.map +1 -0
  23. package/dist/commands/list.js +13 -0
  24. package/dist/commands/list.js.map +1 -0
  25. package/dist/commands/search.d.ts +13 -0
  26. package/dist/commands/search.d.ts.map +1 -0
  27. package/dist/commands/search.js +79 -0
  28. package/dist/commands/search.js.map +1 -0
  29. package/dist/commands/setup.d.ts +8 -0
  30. package/dist/commands/setup.d.ts.map +1 -0
  31. package/dist/commands/setup.js +32 -0
  32. package/dist/commands/setup.js.map +1 -0
  33. package/dist/commands/status.d.ts +5 -0
  34. package/dist/commands/status.d.ts.map +1 -0
  35. package/dist/commands/status.js +27 -0
  36. package/dist/commands/status.js.map +1 -0
  37. package/dist/components/ActiveSessionsView.d.ts +18 -0
  38. package/dist/components/ActiveSessionsView.d.ts.map +1 -0
  39. package/dist/components/ActiveSessionsView.js +68 -0
  40. package/dist/components/ActiveSessionsView.js.map +1 -0
  41. package/dist/components/AddContextConfirmView.d.ts +21 -0
  42. package/dist/components/AddContextConfirmView.d.ts.map +1 -0
  43. package/dist/components/AddContextConfirmView.js +44 -0
  44. package/dist/components/AddContextConfirmView.js.map +1 -0
  45. package/dist/components/App.d.ts +11 -0
  46. package/dist/components/App.d.ts.map +1 -0
  47. package/dist/components/App.js +292 -0
  48. package/dist/components/App.js.map +1 -0
  49. package/dist/components/ArchiveBrowserView.d.ts +40 -0
  50. package/dist/components/ArchiveBrowserView.d.ts.map +1 -0
  51. package/dist/components/ArchiveBrowserView.js +161 -0
  52. package/dist/components/ArchiveBrowserView.js.map +1 -0
  53. package/dist/components/ArchiveInitProgressView.d.ts +16 -0
  54. package/dist/components/ArchiveInitProgressView.d.ts.map +1 -0
  55. package/dist/components/ArchiveInitProgressView.js +72 -0
  56. package/dist/components/ArchiveInitProgressView.js.map +1 -0
  57. package/dist/components/AutoCompactToggle.d.ts +16 -0
  58. package/dist/components/AutoCompactToggle.d.ts.map +1 -0
  59. package/dist/components/AutoCompactToggle.js +12 -0
  60. package/dist/components/AutoCompactToggle.js.map +1 -0
  61. package/dist/components/BottomControls.d.ts +12 -0
  62. package/dist/components/BottomControls.d.ts.map +1 -0
  63. package/dist/components/BottomControls.js +11 -0
  64. package/dist/components/BottomControls.js.map +1 -0
  65. package/dist/components/CompactHeader.d.ts +21 -0
  66. package/dist/components/CompactHeader.d.ts.map +1 -0
  67. package/dist/components/CompactHeader.js +63 -0
  68. package/dist/components/CompactHeader.js.map +1 -0
  69. package/dist/components/CompactPanel.d.ts +22 -0
  70. package/dist/components/CompactPanel.d.ts.map +1 -0
  71. package/dist/components/CompactPanel.js +31 -0
  72. package/dist/components/CompactPanel.js.map +1 -0
  73. package/dist/components/ContentBox.d.ts +14 -0
  74. package/dist/components/ContentBox.d.ts.map +1 -0
  75. package/dist/components/ContentBox.js +24 -0
  76. package/dist/components/ContentBox.js.map +1 -0
  77. package/dist/components/ContextProgress.d.ts +14 -0
  78. package/dist/components/ContextProgress.d.ts.map +1 -0
  79. package/dist/components/ContextProgress.js +36 -0
  80. package/dist/components/ContextProgress.js.map +1 -0
  81. package/dist/components/Dashboard.d.ts +46 -0
  82. package/dist/components/Dashboard.d.ts.map +1 -0
  83. package/dist/components/Dashboard.js +67 -0
  84. package/dist/components/Dashboard.js.map +1 -0
  85. package/dist/components/FilterSelectionView.d.ts +15 -0
  86. package/dist/components/FilterSelectionView.d.ts.map +1 -0
  87. package/dist/components/FilterSelectionView.js +27 -0
  88. package/dist/components/FilterSelectionView.js.map +1 -0
  89. package/dist/components/GoogleDocsBrowserView.d.ts +20 -0
  90. package/dist/components/GoogleDocsBrowserView.d.ts.map +1 -0
  91. package/dist/components/GoogleDocsBrowserView.js +72 -0
  92. package/dist/components/GoogleDocsBrowserView.js.map +1 -0
  93. package/dist/components/HandoffBrowserView.d.ts +20 -0
  94. package/dist/components/HandoffBrowserView.d.ts.map +1 -0
  95. package/dist/components/HandoffBrowserView.js +66 -0
  96. package/dist/components/HandoffBrowserView.js.map +1 -0
  97. package/dist/components/Header.d.ts +14 -0
  98. package/dist/components/Header.d.ts.map +1 -0
  99. package/dist/components/Header.js +16 -0
  100. package/dist/components/Header.js.map +1 -0
  101. package/dist/components/HorizontalMenu.d.ts +24 -0
  102. package/dist/components/HorizontalMenu.d.ts.map +1 -0
  103. package/dist/components/HorizontalMenu.js +20 -0
  104. package/dist/components/HorizontalMenu.js.map +1 -0
  105. package/dist/components/ImageMascot.d.ts +8 -0
  106. package/dist/components/ImageMascot.d.ts.map +1 -0
  107. package/dist/components/ImageMascot.js +7 -0
  108. package/dist/components/ImageMascot.js.map +1 -0
  109. package/dist/components/LLMWorkingView.d.ts +19 -0
  110. package/dist/components/LLMWorkingView.d.ts.map +1 -0
  111. package/dist/components/LLMWorkingView.js +72 -0
  112. package/dist/components/LLMWorkingView.js.map +1 -0
  113. package/dist/components/LoadContextView.d.ts +22 -0
  114. package/dist/components/LoadContextView.d.ts.map +1 -0
  115. package/dist/components/LoadContextView.js +83 -0
  116. package/dist/components/LoadContextView.js.map +1 -0
  117. package/dist/components/MainMenuView.d.ts +20 -0
  118. package/dist/components/MainMenuView.d.ts.map +1 -0
  119. package/dist/components/MainMenuView.js +49 -0
  120. package/dist/components/MainMenuView.js.map +1 -0
  121. package/dist/components/Mascot.d.ts +24 -0
  122. package/dist/components/Mascot.d.ts.map +1 -0
  123. package/dist/components/Mascot.js +32 -0
  124. package/dist/components/Mascot.js.map +1 -0
  125. package/dist/components/Menu.d.ts +22 -0
  126. package/dist/components/Menu.d.ts.map +1 -0
  127. package/dist/components/Menu.js +28 -0
  128. package/dist/components/Menu.js.map +1 -0
  129. package/dist/components/NotionBrowserView.d.ts +21 -0
  130. package/dist/components/NotionBrowserView.d.ts.map +1 -0
  131. package/dist/components/NotionBrowserView.js +75 -0
  132. package/dist/components/NotionBrowserView.js.map +1 -0
  133. package/dist/components/ObsidianBrowserView.d.ts +21 -0
  134. package/dist/components/ObsidianBrowserView.d.ts.map +1 -0
  135. package/dist/components/ObsidianBrowserView.js +74 -0
  136. package/dist/components/ObsidianBrowserView.js.map +1 -0
  137. package/dist/components/ObsidianConfigView.d.ts +19 -0
  138. package/dist/components/ObsidianConfigView.d.ts.map +1 -0
  139. package/dist/components/ObsidianConfigView.js +45 -0
  140. package/dist/components/ObsidianConfigView.js.map +1 -0
  141. package/dist/components/PlaceholderView.d.ts +15 -0
  142. package/dist/components/PlaceholderView.d.ts.map +1 -0
  143. package/dist/components/PlaceholderView.js +20 -0
  144. package/dist/components/PlaceholderView.js.map +1 -0
  145. package/dist/components/PlanViewerView.d.ts +26 -0
  146. package/dist/components/PlanViewerView.d.ts.map +1 -0
  147. package/dist/components/PlanViewerView.js +170 -0
  148. package/dist/components/PlanViewerView.js.map +1 -0
  149. package/dist/components/ProgressBar.d.ts +24 -0
  150. package/dist/components/ProgressBar.d.ts.map +1 -0
  151. package/dist/components/ProgressBar.js +23 -0
  152. package/dist/components/ProgressBar.js.map +1 -0
  153. package/dist/components/ProjectDashboardView.d.ts +38 -0
  154. package/dist/components/ProjectDashboardView.d.ts.map +1 -0
  155. package/dist/components/ProjectDashboardView.js +129 -0
  156. package/dist/components/ProjectDashboardView.js.map +1 -0
  157. package/dist/components/SaveContextView.d.ts +32 -0
  158. package/dist/components/SaveContextView.d.ts.map +1 -0
  159. package/dist/components/SaveContextView.js +41 -0
  160. package/dist/components/SaveContextView.js.map +1 -0
  161. package/dist/components/SessionDetails.d.ts +14 -0
  162. package/dist/components/SessionDetails.d.ts.map +1 -0
  163. package/dist/components/SessionDetails.js +87 -0
  164. package/dist/components/SessionDetails.js.map +1 -0
  165. package/dist/components/SessionsExperimentView.d.ts +35 -0
  166. package/dist/components/SessionsExperimentView.d.ts.map +1 -0
  167. package/dist/components/SessionsExperimentView.js +347 -0
  168. package/dist/components/SessionsExperimentView.js.map +1 -0
  169. package/dist/components/SessionsList.d.ts +20 -0
  170. package/dist/components/SessionsList.d.ts.map +1 -0
  171. package/dist/components/SessionsList.js +75 -0
  172. package/dist/components/SessionsList.js.map +1 -0
  173. package/dist/components/SettingsView.d.ts +48 -0
  174. package/dist/components/SettingsView.d.ts.map +1 -0
  175. package/dist/components/SettingsView.js +156 -0
  176. package/dist/components/SettingsView.js.map +1 -0
  177. package/dist/components/SourceSelectionView.d.ts +26 -0
  178. package/dist/components/SourceSelectionView.d.ts.map +1 -0
  179. package/dist/components/SourceSelectionView.js +109 -0
  180. package/dist/components/SourceSelectionView.js.map +1 -0
  181. package/dist/components/VerticalMenu.d.ts +18 -0
  182. package/dist/components/VerticalMenu.d.ts.map +1 -0
  183. package/dist/components/VerticalMenu.js +15 -0
  184. package/dist/components/VerticalMenu.js.map +1 -0
  185. package/dist/components/ascii-art/index.d.ts +6 -0
  186. package/dist/components/ascii-art/index.d.ts.map +1 -0
  187. package/dist/components/ascii-art/index.js +6 -0
  188. package/dist/components/ascii-art/index.js.map +1 -0
  189. package/dist/components/ascii-art/progress.d.ts +53 -0
  190. package/dist/components/ascii-art/progress.d.ts.map +1 -0
  191. package/dist/components/ascii-art/progress.js +102 -0
  192. package/dist/components/ascii-art/progress.js.map +1 -0
  193. package/dist/components/ascii-art/scene.d.ts +34 -0
  194. package/dist/components/ascii-art/scene.d.ts.map +1 -0
  195. package/dist/components/ascii-art/scene.js +72 -0
  196. package/dist/components/ascii-art/scene.js.map +1 -0
  197. package/dist/components/index.d.ts +27 -0
  198. package/dist/components/index.d.ts.map +1 -0
  199. package/dist/components/index.js +25 -0
  200. package/dist/components/index.js.map +1 -0
  201. package/dist/components/layout/HorizontalLayout.d.ts +19 -0
  202. package/dist/components/layout/HorizontalLayout.d.ts.map +1 -0
  203. package/dist/components/layout/HorizontalLayout.js +62 -0
  204. package/dist/components/layout/HorizontalLayout.js.map +1 -0
  205. package/dist/components/layout/VerticalLayout.d.ts +16 -0
  206. package/dist/components/layout/VerticalLayout.d.ts.map +1 -0
  207. package/dist/components/layout/VerticalLayout.js +32 -0
  208. package/dist/components/layout/VerticalLayout.js.map +1 -0
  209. package/dist/components/layout/index.d.ts +6 -0
  210. package/dist/components/layout/index.d.ts.map +1 -0
  211. package/dist/components/layout/index.js +4 -0
  212. package/dist/components/layout/index.js.map +1 -0
  213. package/dist/components/layout/theme.d.ts +20 -0
  214. package/dist/components/layout/theme.d.ts.map +1 -0
  215. package/dist/components/layout/theme.js +23 -0
  216. package/dist/components/layout/theme.js.map +1 -0
  217. package/dist/components/setup/DoneStep.d.ts +7 -0
  218. package/dist/components/setup/DoneStep.d.ts.map +1 -0
  219. package/dist/components/setup/DoneStep.js +31 -0
  220. package/dist/components/setup/DoneStep.js.map +1 -0
  221. package/dist/components/setup/InstallingStep.d.ts +11 -0
  222. package/dist/components/setup/InstallingStep.d.ts.map +1 -0
  223. package/dist/components/setup/InstallingStep.js +27 -0
  224. package/dist/components/setup/InstallingStep.js.map +1 -0
  225. package/dist/components/setup/OptionsStep.d.ts +9 -0
  226. package/dist/components/setup/OptionsStep.d.ts.map +1 -0
  227. package/dist/components/setup/OptionsStep.js +39 -0
  228. package/dist/components/setup/OptionsStep.js.map +1 -0
  229. package/dist/components/setup/PrerequisitesStep.d.ts +7 -0
  230. package/dist/components/setup/PrerequisitesStep.d.ts.map +1 -0
  231. package/dist/components/setup/PrerequisitesStep.js +31 -0
  232. package/dist/components/setup/PrerequisitesStep.js.map +1 -0
  233. package/dist/components/setup/SetupFrame.d.ts +17 -0
  234. package/dist/components/setup/SetupFrame.d.ts.map +1 -0
  235. package/dist/components/setup/SetupFrame.js +33 -0
  236. package/dist/components/setup/SetupFrame.js.map +1 -0
  237. package/dist/components/setup/SetupWizard.d.ts +9 -0
  238. package/dist/components/setup/SetupWizard.d.ts.map +1 -0
  239. package/dist/components/setup/SetupWizard.js +149 -0
  240. package/dist/components/setup/SetupWizard.js.map +1 -0
  241. package/dist/components/setup/Spinner.d.ts +10 -0
  242. package/dist/components/setup/Spinner.d.ts.map +1 -0
  243. package/dist/components/setup/Spinner.js +20 -0
  244. package/dist/components/setup/Spinner.js.map +1 -0
  245. package/dist/components/setup/SyncStep.d.ts +11 -0
  246. package/dist/components/setup/SyncStep.d.ts.map +1 -0
  247. package/dist/components/setup/SyncStep.js +47 -0
  248. package/dist/components/setup/SyncStep.js.map +1 -0
  249. package/dist/components/setup/VerificationStep.d.ts +7 -0
  250. package/dist/components/setup/VerificationStep.d.ts.map +1 -0
  251. package/dist/components/setup/VerificationStep.js +27 -0
  252. package/dist/components/setup/VerificationStep.js.map +1 -0
  253. package/dist/components/setup/WelcomeStep.d.ts +6 -0
  254. package/dist/components/setup/WelcomeStep.d.ts.map +1 -0
  255. package/dist/components/setup/WelcomeStep.js +17 -0
  256. package/dist/components/setup/WelcomeStep.js.map +1 -0
  257. package/dist/components/shared/ProgressLine.d.ts +10 -0
  258. package/dist/components/shared/ProgressLine.d.ts.map +1 -0
  259. package/dist/components/shared/ProgressLine.js +18 -0
  260. package/dist/components/shared/ProgressLine.js.map +1 -0
  261. package/dist/components/shared/ProjectLine.d.ts +10 -0
  262. package/dist/components/shared/ProjectLine.d.ts.map +1 -0
  263. package/dist/components/shared/ProjectLine.js +19 -0
  264. package/dist/components/shared/ProjectLine.js.map +1 -0
  265. package/dist/components/shared/ScanningIndicator.d.ts +9 -0
  266. package/dist/components/shared/ScanningIndicator.d.ts.map +1 -0
  267. package/dist/components/shared/ScanningIndicator.js +22 -0
  268. package/dist/components/shared/ScanningIndicator.js.map +1 -0
  269. package/dist/components/shared/StatusLine.d.ts +13 -0
  270. package/dist/components/shared/StatusLine.d.ts.map +1 -0
  271. package/dist/components/shared/StatusLine.js +24 -0
  272. package/dist/components/shared/StatusLine.js.map +1 -0
  273. package/dist/components/shared/StatusLine.test.d.ts +8 -0
  274. package/dist/components/shared/StatusLine.test.d.ts.map +1 -0
  275. package/dist/components/shared/StatusLine.test.js +50 -0
  276. package/dist/components/shared/StatusLine.test.js.map +1 -0
  277. package/dist/components/shared/index.d.ts +4 -0
  278. package/dist/components/shared/index.d.ts.map +1 -0
  279. package/dist/components/shared/index.js +4 -0
  280. package/dist/components/shared/index.js.map +1 -0
  281. package/dist/handoff/catalog.test.d.ts +5 -0
  282. package/dist/handoff/catalog.test.d.ts.map +1 -0
  283. package/dist/handoff/catalog.test.js +172 -0
  284. package/dist/handoff/catalog.test.js.map +1 -0
  285. package/dist/handoff/subagents.test.d.ts +8 -0
  286. package/dist/handoff/subagents.test.d.ts.map +1 -0
  287. package/dist/handoff/subagents.test.js +139 -0
  288. package/dist/handoff/subagents.test.js.map +1 -0
  289. package/dist/hooks/useAddContextFlow.d.ts +29 -0
  290. package/dist/hooks/useAddContextFlow.d.ts.map +1 -0
  291. package/dist/hooks/useAddContextFlow.js +83 -0
  292. package/dist/hooks/useAddContextFlow.js.map +1 -0
  293. package/dist/hooks/useArchiveBrowser.d.ts +37 -0
  294. package/dist/hooks/useArchiveBrowser.d.ts.map +1 -0
  295. package/dist/hooks/useArchiveBrowser.js +175 -0
  296. package/dist/hooks/useArchiveBrowser.js.map +1 -0
  297. package/dist/hooks/useClaudeToken.d.ts +29 -0
  298. package/dist/hooks/useClaudeToken.d.ts.map +1 -0
  299. package/dist/hooks/useClaudeToken.js +166 -0
  300. package/dist/hooks/useClaudeToken.js.map +1 -0
  301. package/dist/hooks/useGoogleDocsBrowser.d.ts +29 -0
  302. package/dist/hooks/useGoogleDocsBrowser.d.ts.map +1 -0
  303. package/dist/hooks/useGoogleDocsBrowser.js +146 -0
  304. package/dist/hooks/useGoogleDocsBrowser.js.map +1 -0
  305. package/dist/hooks/useHandoffBrowser.d.ts +27 -0
  306. package/dist/hooks/useHandoffBrowser.d.ts.map +1 -0
  307. package/dist/hooks/useHandoffBrowser.js +92 -0
  308. package/dist/hooks/useHandoffBrowser.js.map +1 -0
  309. package/dist/hooks/useJacquesClient.d.ts +69 -0
  310. package/dist/hooks/useJacquesClient.d.ts.map +1 -0
  311. package/dist/hooks/useJacquesClient.js +248 -0
  312. package/dist/hooks/useJacquesClient.js.map +1 -0
  313. package/dist/hooks/useLlmWorking.d.ts +30 -0
  314. package/dist/hooks/useLlmWorking.d.ts.map +1 -0
  315. package/dist/hooks/useLlmWorking.js +127 -0
  316. package/dist/hooks/useLlmWorking.js.map +1 -0
  317. package/dist/hooks/useLoadContext.d.ts +27 -0
  318. package/dist/hooks/useLoadContext.d.ts.map +1 -0
  319. package/dist/hooks/useLoadContext.js +102 -0
  320. package/dist/hooks/useLoadContext.js.map +1 -0
  321. package/dist/hooks/useNotification.d.ts +36 -0
  322. package/dist/hooks/useNotification.d.ts.map +1 -0
  323. package/dist/hooks/useNotification.js +89 -0
  324. package/dist/hooks/useNotification.js.map +1 -0
  325. package/dist/hooks/useNotification.test.d.ts +9 -0
  326. package/dist/hooks/useNotification.test.d.ts.map +1 -0
  327. package/dist/hooks/useNotification.test.js +144 -0
  328. package/dist/hooks/useNotification.test.js.map +1 -0
  329. package/dist/hooks/useNotionBrowser.d.ts +30 -0
  330. package/dist/hooks/useNotionBrowser.d.ts.map +1 -0
  331. package/dist/hooks/useNotionBrowser.js +154 -0
  332. package/dist/hooks/useNotionBrowser.js.map +1 -0
  333. package/dist/hooks/useObsidianBrowser.d.ts +42 -0
  334. package/dist/hooks/useObsidianBrowser.d.ts.map +1 -0
  335. package/dist/hooks/useObsidianBrowser.js +63 -0
  336. package/dist/hooks/useObsidianBrowser.js.map +1 -0
  337. package/dist/hooks/useObsidianConfig.d.ts +28 -0
  338. package/dist/hooks/useObsidianConfig.d.ts.map +1 -0
  339. package/dist/hooks/useObsidianConfig.js +119 -0
  340. package/dist/hooks/useObsidianConfig.js.map +1 -0
  341. package/dist/hooks/useObsidianFileBrowser.d.ts +29 -0
  342. package/dist/hooks/useObsidianFileBrowser.d.ts.map +1 -0
  343. package/dist/hooks/useObsidianFileBrowser.js +114 -0
  344. package/dist/hooks/useObsidianFileBrowser.js.map +1 -0
  345. package/dist/hooks/useProjectDashboard.d.ts +38 -0
  346. package/dist/hooks/useProjectDashboard.d.ts.map +1 -0
  347. package/dist/hooks/useProjectDashboard.js +224 -0
  348. package/dist/hooks/useProjectDashboard.js.map +1 -0
  349. package/dist/hooks/useProjectSelector.d.ts +17 -0
  350. package/dist/hooks/useProjectSelector.d.ts.map +1 -0
  351. package/dist/hooks/useProjectSelector.js +43 -0
  352. package/dist/hooks/useProjectSelector.js.map +1 -0
  353. package/dist/hooks/useProjectSelector.test.d.ts +7 -0
  354. package/dist/hooks/useProjectSelector.test.d.ts.map +1 -0
  355. package/dist/hooks/useProjectSelector.test.js +117 -0
  356. package/dist/hooks/useProjectSelector.test.js.map +1 -0
  357. package/dist/hooks/useSaveFlow.d.ts +30 -0
  358. package/dist/hooks/useSaveFlow.d.ts.map +1 -0
  359. package/dist/hooks/useSaveFlow.js +195 -0
  360. package/dist/hooks/useSaveFlow.js.map +1 -0
  361. package/dist/hooks/useSessions.test.d.ts +7 -0
  362. package/dist/hooks/useSessions.test.d.ts.map +1 -0
  363. package/dist/hooks/useSessions.test.js +153 -0
  364. package/dist/hooks/useSessions.test.js.map +1 -0
  365. package/dist/hooks/useSessionsExperiment.d.ts +97 -0
  366. package/dist/hooks/useSessionsExperiment.d.ts.map +1 -0
  367. package/dist/hooks/useSessionsExperiment.js +321 -0
  368. package/dist/hooks/useSessionsExperiment.js.map +1 -0
  369. package/dist/hooks/useSettings.d.ts +47 -0
  370. package/dist/hooks/useSettings.d.ts.map +1 -0
  371. package/dist/hooks/useSettings.js +245 -0
  372. package/dist/hooks/useSettings.js.map +1 -0
  373. package/dist/hooks/useSetupWizard.d.ts +35 -0
  374. package/dist/hooks/useSetupWizard.d.ts.map +1 -0
  375. package/dist/hooks/useSetupWizard.js +438 -0
  376. package/dist/hooks/useSetupWizard.js.map +1 -0
  377. package/dist/hooks/useUsageLimits.d.ts +24 -0
  378. package/dist/hooks/useUsageLimits.d.ts.map +1 -0
  379. package/dist/hooks/useUsageLimits.js +58 -0
  380. package/dist/hooks/useUsageLimits.js.map +1 -0
  381. package/dist/hooks/useUsageLimits.test.d.ts +7 -0
  382. package/dist/hooks/useUsageLimits.test.d.ts.map +1 -0
  383. package/dist/hooks/useUsageLimits.test.js +136 -0
  384. package/dist/hooks/useUsageLimits.test.js.map +1 -0
  385. package/dist/hooks/useWorktrees.d.ts +28 -0
  386. package/dist/hooks/useWorktrees.d.ts.map +1 -0
  387. package/dist/hooks/useWorktrees.js +57 -0
  388. package/dist/hooks/useWorktrees.js.map +1 -0
  389. package/dist/hooks/useWorktrees.test.d.ts +7 -0
  390. package/dist/hooks/useWorktrees.test.d.ts.map +1 -0
  391. package/dist/hooks/useWorktrees.test.js +119 -0
  392. package/dist/hooks/useWorktrees.test.js.map +1 -0
  393. package/dist/templates/compact-prompt.d.ts +16 -0
  394. package/dist/templates/compact-prompt.d.ts.map +1 -0
  395. package/dist/templates/compact-prompt.js +47 -0
  396. package/dist/templates/compact-prompt.js.map +1 -0
  397. package/dist/templates/context-skill.d.ts +8 -0
  398. package/dist/templates/context-skill.d.ts.map +1 -0
  399. package/dist/templates/context-skill.js +42 -0
  400. package/dist/templates/context-skill.js.map +1 -0
  401. package/dist/types.d.ts +127 -0
  402. package/dist/types.d.ts.map +1 -0
  403. package/dist/types.js +8 -0
  404. package/dist/types.js.map +1 -0
  405. package/dist/utils/activity.d.ts +17 -0
  406. package/dist/utils/activity.d.ts.map +1 -0
  407. package/dist/utils/activity.js +78 -0
  408. package/dist/utils/activity.js.map +1 -0
  409. package/dist/utils/bottom-controls.d.ts +24 -0
  410. package/dist/utils/bottom-controls.d.ts.map +1 -0
  411. package/dist/utils/bottom-controls.js +29 -0
  412. package/dist/utils/bottom-controls.js.map +1 -0
  413. package/dist/utils/clipboard.d.ts +2 -0
  414. package/dist/utils/clipboard.d.ts.map +1 -0
  415. package/dist/utils/clipboard.js +20 -0
  416. package/dist/utils/clipboard.js.map +1 -0
  417. package/dist/utils/constants.d.ts +6 -0
  418. package/dist/utils/constants.d.ts.map +1 -0
  419. package/dist/utils/constants.js +6 -0
  420. package/dist/utils/constants.js.map +1 -0
  421. package/dist/utils/format.d.ts +17 -0
  422. package/dist/utils/format.d.ts.map +1 -0
  423. package/dist/utils/format.js +31 -0
  424. package/dist/utils/format.js.map +1 -0
  425. package/dist/utils/session-mode.d.ts +14 -0
  426. package/dist/utils/session-mode.d.ts.map +1 -0
  427. package/dist/utils/session-mode.js +29 -0
  428. package/dist/utils/session-mode.js.map +1 -0
  429. package/dist/utils/session-mode.test.d.ts +7 -0
  430. package/dist/utils/session-mode.test.d.ts.map +1 -0
  431. package/dist/utils/session-mode.test.js +102 -0
  432. package/dist/utils/session-mode.test.js.map +1 -0
  433. package/dist/utils/sessions-items-builder.d.ts +29 -0
  434. package/dist/utils/sessions-items-builder.d.ts.map +1 -0
  435. package/dist/utils/sessions-items-builder.js +394 -0
  436. package/dist/utils/sessions-items-builder.js.map +1 -0
  437. package/dist/utils/settings.d.ts +100 -0
  438. package/dist/utils/settings.d.ts.map +1 -0
  439. package/dist/utils/settings.js +206 -0
  440. package/dist/utils/settings.js.map +1 -0
  441. package/dist/websocket-client.d.ts +70 -0
  442. package/dist/websocket-client.d.ts.map +1 -0
  443. package/dist/websocket-client.js +188 -0
  444. package/dist/websocket-client.js.map +1 -0
  445. package/hooks/adapters/__init__.py +17 -0
  446. package/hooks/adapters/__pycache__/__init__.cpython-311.pyc +0 -0
  447. package/hooks/adapters/__pycache__/__init__.cpython-313.pyc +0 -0
  448. package/hooks/adapters/__pycache__/__init__.cpython-314.pyc +0 -0
  449. package/hooks/adapters/__pycache__/base.cpython-311.pyc +0 -0
  450. package/hooks/adapters/__pycache__/base.cpython-313.pyc +0 -0
  451. package/hooks/adapters/__pycache__/base.cpython-314.pyc +0 -0
  452. package/hooks/adapters/__pycache__/calibration.cpython-311.pyc +0 -0
  453. package/hooks/adapters/__pycache__/calibration.cpython-313.pyc +0 -0
  454. package/hooks/adapters/__pycache__/calibration.cpython-314.pyc +0 -0
  455. package/hooks/adapters/__pycache__/claude_code.cpython-311.pyc +0 -0
  456. package/hooks/adapters/__pycache__/claude_code.cpython-313.pyc +0 -0
  457. package/hooks/adapters/__pycache__/claude_code.cpython-314.pyc +0 -0
  458. package/hooks/adapters/__pycache__/cursor.cpython-311.pyc +0 -0
  459. package/hooks/adapters/__pycache__/cursor.cpython-313.pyc +0 -0
  460. package/hooks/adapters/__pycache__/cursor.cpython-314.pyc +0 -0
  461. package/hooks/adapters/__pycache__/skills.cpython-311.pyc +0 -0
  462. package/hooks/adapters/__pycache__/skills.cpython-313.pyc +0 -0
  463. package/hooks/adapters/__pycache__/skills.cpython-314.pyc +0 -0
  464. package/hooks/adapters/__pycache__/test_adapters.cpython-311-pytest-9.0.2.pyc +0 -0
  465. package/hooks/adapters/__pycache__/test_adapters.cpython-313.pyc +0 -0
  466. package/hooks/adapters/__pycache__/test_calibration.cpython-311-pytest-9.0.2.pyc +0 -0
  467. package/hooks/adapters/__pycache__/test_skills.cpython-311-pytest-9.0.2.pyc +0 -0
  468. package/hooks/adapters/__pycache__/test_tokenizer.cpython-311-pytest-9.0.2.pyc +0 -0
  469. package/hooks/adapters/__pycache__/tokenizer.cpython-311.pyc +0 -0
  470. package/hooks/adapters/__pycache__/tokenizer.cpython-313.pyc +0 -0
  471. package/hooks/adapters/__pycache__/tokenizer.cpython-314.pyc +0 -0
  472. package/hooks/adapters/base.py +459 -0
  473. package/hooks/adapters/calibration.py +236 -0
  474. package/hooks/adapters/claude_code.py +316 -0
  475. package/hooks/adapters/context_parser.py +288 -0
  476. package/hooks/adapters/cursor.py +258 -0
  477. package/hooks/adapters/skills.py +160 -0
  478. package/hooks/adapters/template.py +281 -0
  479. package/hooks/adapters/test_adapters.py +516 -0
  480. package/hooks/adapters/test_calibration.py +235 -0
  481. package/hooks/adapters/test_skills.py +162 -0
  482. package/hooks/adapters/test_tokenizer.py +158 -0
  483. package/hooks/adapters/tokenizer.py +192 -0
  484. package/hooks/claude-code/pre-tool-use.py +36 -0
  485. package/hooks/claude-code/register-session.py +35 -0
  486. package/hooks/claude-code/report-activity.py +32 -0
  487. package/hooks/claude-code/session-idle.py +32 -0
  488. package/hooks/claude-code/statusline.sh +91 -0
  489. package/hooks/claude-code/unregister-session.py +32 -0
  490. package/hooks/cursor/README.md +61 -0
  491. package/hooks/cursor/after-agent-response.py +97 -0
  492. package/hooks/cursor/hooks.json.template +30 -0
  493. package/hooks/cursor/post-tool-use.py +32 -0
  494. package/hooks/cursor/pre-compact.py +61 -0
  495. package/hooks/cursor/session-end.py +32 -0
  496. package/hooks/cursor/session-start.py +66 -0
  497. package/hooks/git-detect.sh +47 -0
  498. package/hooks/install.py +441 -0
  499. package/hooks/jacques-register-session.py +286 -0
  500. package/hooks/jacques-report-activity.py +145 -0
  501. package/hooks/jacques-session-idle.py +57 -0
  502. package/hooks/jacques-unregister-session.py +57 -0
  503. package/hooks/requirements.txt +9 -0
  504. package/hooks/statusline.py +457 -0
  505. package/hooks/statusline.sh +212 -0
  506. package/package.json +63 -0
  507. package/skills/jacques-continue/SKILL.md +87 -0
  508. package/skills/jacques-handoff/SKILL.md +147 -0
@@ -0,0 +1,258 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ cursor.py - Cursor Native AI Adapter for Jacques
4
+
5
+ Handles events from Cursor's native AI (sidebar chat).
6
+
7
+ Field Mappings:
8
+ - session_id: conversation_id
9
+ - project_path: workspace_roots[0]
10
+ - context_metrics: from preCompact event
11
+
12
+ Hook Events (configured in .cursor/hooks.json):
13
+ - sessionStart → session_start
14
+ - sessionEnd → session_end
15
+ - postToolUse → activity
16
+ - preCompact → context_update (contains context metrics!)
17
+
18
+ Key Discovery:
19
+ Cursor's preCompact event provides context metrics that allow us to display
20
+ context usage percentage just like Claude Code CLI!
21
+ """
22
+ import os
23
+ from typing import Optional
24
+ from .base import BaseAdapter
25
+
26
+
27
+ class CursorAdapter(BaseAdapter):
28
+ """
29
+ Adapter for Cursor Native AI sessions.
30
+
31
+ Cursor provides session data via hooks configured in
32
+ .cursor/hooks.json (per-project) or global Cursor settings.
33
+
34
+ Note: Cursor uses different field names than Claude Code:
35
+ - conversation_id instead of session_id
36
+ - workspace_roots[] instead of workspace.project_dir
37
+ """
38
+
39
+ @property
40
+ def source(self) -> str:
41
+ return 'cursor'
42
+
43
+ def get_session_id(self, input_data: dict) -> Optional[str]:
44
+ """
45
+ Extract session ID from Cursor input.
46
+
47
+ Cursor uses 'conversation_id' as the session identifier.
48
+ """
49
+ return input_data.get('conversation_id')
50
+
51
+ def get_project_path(self, input_data: dict) -> Optional[str]:
52
+ """
53
+ Extract project path from Cursor input.
54
+
55
+ Cursor provides workspace_roots as an array of open workspace paths.
56
+ We use the first one as the primary project path.
57
+ """
58
+ workspace_roots = input_data.get('workspace_roots', [])
59
+ if workspace_roots and isinstance(workspace_roots, list):
60
+ return workspace_roots[0]
61
+ return ''
62
+
63
+ def get_model(self, input_data: dict) -> Optional[str]:
64
+ """Extract model name from Cursor input."""
65
+ # Cursor may provide model info in different fields
66
+ return input_data.get('model') or input_data.get('model_name')
67
+
68
+ # =========================================================================
69
+ # Session Start Payload
70
+ # =========================================================================
71
+
72
+ def build_session_start_payload(self, input_data: dict) -> Optional[dict]:
73
+ """
74
+ Build payload for session_start event.
75
+
76
+ Called from sessionStart hook (session-start.py).
77
+ """
78
+ session_id = self.validate_session_id(input_data)
79
+ if not session_id:
80
+ return None
81
+
82
+ # Extract project info
83
+ project_info = self.extract_project_info(input_data)
84
+
85
+ # Cursor doesn't have transcript files like Claude Code
86
+ # Generate title from project name
87
+ session_title = self.generate_fallback_title(project_info['project'])
88
+
89
+ # Get terminal identity (useful for identification)
90
+ terminal = self.get_terminal_identity()
91
+ terminal_key = self.build_terminal_key(terminal)
92
+
93
+ return self.build_base_payload(
94
+ event='session_start',
95
+ session_id=session_id,
96
+ session_title=session_title,
97
+ transcript_path=None, # Cursor doesn't have transcripts
98
+ cwd=project_info['cwd'],
99
+ project=project_info['project'],
100
+ project_dir=project_info['project_path'],
101
+ model=self.get_model(input_data),
102
+ hook_source='startup',
103
+ terminal=terminal,
104
+ terminal_key=terminal_key,
105
+ # Cursor-specific fields
106
+ workspace_roots=input_data.get('workspace_roots', []),
107
+ )
108
+
109
+ # =========================================================================
110
+ # Context Estimate Payload (from token estimation)
111
+ # =========================================================================
112
+
113
+ def build_context_estimate_payload(
114
+ self,
115
+ input_data: dict,
116
+ estimated_tokens: int,
117
+ model: str = None
118
+ ) -> Optional[dict]:
119
+ """
120
+ Build payload for context_update event from token estimation.
121
+
122
+ Used by afterAgentResponse hook to send estimated context metrics.
123
+
124
+ Args:
125
+ input_data: Hook input data
126
+ estimated_tokens: Token count estimated from transcript
127
+ model: Model name (for context window lookup)
128
+
129
+ Returns:
130
+ context_update payload with is_estimate=True flag.
131
+ """
132
+ from . import tokenizer
133
+
134
+ session_id = self.validate_session_id(input_data)
135
+ if not session_id:
136
+ return None
137
+
138
+ # Get model from input or use provided
139
+ if not model:
140
+ model = self.get_model(input_data)
141
+
142
+ # Calculate context metrics
143
+ metrics = tokenizer.calculate_context_metrics(estimated_tokens, model)
144
+
145
+ # Get project info
146
+ project_info = self.extract_project_info(input_data)
147
+
148
+ return self.build_base_payload(
149
+ event='context_update',
150
+ session_id=session_id,
151
+ used_percentage=metrics['used_percentage'],
152
+ remaining_percentage=metrics['remaining_percentage'],
153
+ context_window_size=metrics['context_window_size'],
154
+ total_input_tokens=estimated_tokens,
155
+ total_output_tokens=0,
156
+ is_estimate=True, # Flag to indicate this is an estimate
157
+ cwd=project_info['cwd'],
158
+ project_dir=project_info['project_path'],
159
+ )
160
+
161
+ # =========================================================================
162
+ # Pre-Compact Payload (Context Metrics!)
163
+ # =========================================================================
164
+
165
+ def build_pre_compact_payload(self, input_data: dict) -> Optional[dict]:
166
+ """
167
+ Build payload for context_update event from preCompact.
168
+
169
+ This is the KEY event for Cursor that provides context metrics!
170
+
171
+ Expected input fields from preCompact:
172
+ - context_usage_percent: Percentage of context used (0-100)
173
+ - context_tokens: Current token count
174
+ - context_window_size: Maximum context window
175
+
176
+ NOTE: The 'model' field in preCompact is the SUMMARIZATION model
177
+ (typically gemini-2.5-flash), NOT the user's selected chat model.
178
+ We don't update model here - it should come from sessionStart.
179
+ """
180
+ session_id = self.validate_session_id(input_data)
181
+ if not session_id:
182
+ return None
183
+
184
+ # Extract context metrics
185
+ used_percentage = input_data.get('context_usage_percent', 0)
186
+ context_tokens = input_data.get('context_tokens', 0)
187
+ context_window_size = input_data.get('context_window_size', 0)
188
+
189
+ # Calculate remaining percentage
190
+ remaining_percentage = 100 - used_percentage if used_percentage else 100
191
+
192
+ # Get project info for cwd
193
+ project_info = self.extract_project_info(input_data)
194
+
195
+ # NOTE: Don't use model from preCompact - it's the summarization model
196
+ # (gemini-2.5-flash), not the user's chat model. Leave model empty
197
+ # so it doesn't overwrite the correct model from sessionStart.
198
+
199
+ return self.build_base_payload(
200
+ event='context_update',
201
+ session_id=session_id,
202
+ used_percentage=used_percentage,
203
+ remaining_percentage=remaining_percentage,
204
+ context_window_size=context_window_size,
205
+ total_input_tokens=context_tokens,
206
+ total_output_tokens=0, # Cursor doesn't provide this
207
+ # Don't include model - let sessionStart model persist
208
+ cwd=project_info['cwd'],
209
+ project_dir=project_info['project_path'],
210
+ )
211
+
212
+ # =========================================================================
213
+ # Activity Payload
214
+ # =========================================================================
215
+
216
+ def build_activity_payload(self, input_data: dict) -> Optional[dict]:
217
+ """
218
+ Build payload for activity event.
219
+
220
+ Called from postToolUse hook (post-tool-use.py).
221
+ """
222
+ session_id = self.validate_session_id(input_data)
223
+ if not session_id:
224
+ return None
225
+
226
+ # Extract project info for session title
227
+ project_info = self.extract_project_info(input_data)
228
+ session_title = self.generate_fallback_title(project_info['project'])
229
+
230
+ tool_name = input_data.get('tool_name', 'unknown')
231
+
232
+ return self.build_base_payload(
233
+ event='activity',
234
+ session_id=session_id,
235
+ session_title=session_title,
236
+ tool_name=tool_name,
237
+ terminal_pid=os.getppid(),
238
+ )
239
+
240
+ # =========================================================================
241
+ # Session End Payload
242
+ # =========================================================================
243
+
244
+ def build_session_end_payload(self, input_data: dict) -> Optional[dict]:
245
+ """
246
+ Build payload for session_end event.
247
+
248
+ Called from sessionEnd hook (session-end.py).
249
+ """
250
+ session_id = self.validate_session_id(input_data)
251
+ if not session_id:
252
+ return None
253
+
254
+ return self.build_base_payload(
255
+ event='session_end',
256
+ session_id=session_id,
257
+ terminal_pid=os.getppid(),
258
+ )
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ skills.py - Cursor Agent Skills Detection for Jacques
4
+
5
+ Scans for installed Cursor agent skills and estimates their token overhead.
6
+
7
+ IMPORTANT: Cursor does NOT inject full SKILL.md files into context!
8
+ It only injects skill METADATA (name, description, path) - about 150-200 tokens per skill.
9
+
10
+ Skill locations:
11
+ - ~/.cursor/skills-cursor/*/SKILL.md - User-installed Cursor skills
12
+ - ~/.claude/plugins/cache/**/SKILL.md - Claude plugins (superpowers, etc.)
13
+
14
+ Typical overhead (CORRECTED):
15
+ - 21 skills × ~200 tokens metadata = ~4,200 tokens
16
+ - System prompts: ~2,000 tokens
17
+ - Total: ~6,000-8,000 tokens (~3-4% on 176k context)
18
+ """
19
+ import os
20
+ import re
21
+ from pathlib import Path
22
+ from typing import List, Tuple
23
+
24
+ # Known skill directories
25
+ SKILL_DIRECTORIES = [
26
+ Path.home() / '.cursor' / 'skills-cursor',
27
+ Path.home() / '.claude' / 'plugins' / 'cache',
28
+ ]
29
+
30
+ # Tokens per skill METADATA (not full content!)
31
+ # Cursor uses dynamic context discovery - only name + short description
32
+ # are included statically. Full skill content loaded on-demand.
33
+ # Estimated: ~5-10 tokens for name + ~30-50 tokens for description
34
+ TOKENS_PER_SKILL_METADATA = 50
35
+
36
+ # Base system prompt overhead (Cursor's internal prompts, tools, etc.)
37
+ # Includes: tool definitions, system instructions, user rules
38
+ SYSTEM_PROMPT_TOKENS = 2500
39
+
40
+ # Cache for skill data (computed once per process)
41
+ _skills_cache = None
42
+
43
+
44
+ def find_skill_files() -> List[Path]:
45
+ """
46
+ Find all SKILL.md files in known locations.
47
+
48
+ Returns:
49
+ List of paths to skill files.
50
+ """
51
+ skill_files = []
52
+
53
+ for skill_dir in SKILL_DIRECTORIES:
54
+ if not skill_dir.exists():
55
+ continue
56
+
57
+ # Recursively find all SKILL.md files
58
+ for skill_file in skill_dir.rglob('SKILL.md'):
59
+ skill_files.append(skill_file)
60
+
61
+ return skill_files
62
+
63
+
64
+ def extract_skill_description(skill_file: Path) -> str:
65
+ """
66
+ Extract the description from a SKILL.md file's frontmatter.
67
+
68
+ Returns:
69
+ Description string, or empty if not found.
70
+ """
71
+ try:
72
+ content = skill_file.read_text(encoding='utf-8')
73
+ # Look for description in YAML frontmatter
74
+ match = re.search(r'^---\s*\n.*?description:\s*(.+?)\n.*?^---', content, re.MULTILINE | re.DOTALL)
75
+ if match:
76
+ return match.group(1).strip()
77
+ except Exception:
78
+ pass
79
+ return ""
80
+
81
+
82
+ def estimate_skill_tokens() -> Tuple[int, int]:
83
+ """
84
+ Estimate total token overhead from installed skills.
85
+
86
+ IMPORTANT: Cursor only injects skill METADATA, not full content!
87
+ Each skill adds ~200 tokens of metadata (name, description, path).
88
+
89
+ Returns:
90
+ Tuple of (skill_count, estimated_tokens)
91
+ """
92
+ global _skills_cache
93
+
94
+ if _skills_cache is not None:
95
+ return _skills_cache
96
+
97
+ skill_files = find_skill_files()
98
+ skill_count = len(skill_files)
99
+
100
+ # Cursor injects metadata only, not full skill content
101
+ # ~200 tokens per skill for the <agent_skill> tag with path and description
102
+ estimated_tokens = skill_count * TOKENS_PER_SKILL_METADATA
103
+
104
+ _skills_cache = (skill_count, estimated_tokens)
105
+ return _skills_cache
106
+
107
+
108
+ def get_initial_context_estimate(model: str = None) -> dict:
109
+ """
110
+ Get initial context estimate including skill metadata overhead.
111
+
112
+ This provides a more accurate starting point than 0%.
113
+
114
+ Args:
115
+ model: Model name for context window lookup
116
+
117
+ Returns:
118
+ Dict with skill_count, estimated_tokens, and context metrics.
119
+ """
120
+ from . import tokenizer
121
+
122
+ skill_count, skill_tokens = estimate_skill_tokens()
123
+
124
+ # Total = skill metadata + system prompts
125
+ total_initial_tokens = skill_tokens + SYSTEM_PROMPT_TOKENS
126
+
127
+ # Calculate context metrics
128
+ context_window = tokenizer.get_context_window(model)
129
+ used_percentage = tokenizer.calculate_context_percentage(total_initial_tokens, context_window)
130
+
131
+ return {
132
+ 'skill_count': skill_count,
133
+ 'skill_tokens': skill_tokens,
134
+ 'system_prompt_tokens': SYSTEM_PROMPT_TOKENS,
135
+ 'total_initial_tokens': total_initial_tokens,
136
+ 'used_percentage': round(used_percentage, 1),
137
+ 'remaining_percentage': round(100 - used_percentage, 1),
138
+ 'context_window_size': context_window,
139
+ }
140
+
141
+
142
+ def get_skills_summary() -> str:
143
+ """
144
+ Get a human-readable summary of installed skills.
145
+
146
+ Returns:
147
+ Summary string for logging/debugging.
148
+ """
149
+ skill_count, estimated_tokens = estimate_skill_tokens()
150
+
151
+ return (
152
+ f"{skill_count} skills installed, "
153
+ f"~{estimated_tokens:,} tokens overhead"
154
+ )
155
+
156
+
157
+ def clear_cache() -> None:
158
+ """Clear the skills cache (useful for testing or when skills change)."""
159
+ global _skills_cache
160
+ _skills_cache = None
@@ -0,0 +1,281 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ template.py - Template Adapter for New Jacques Sources
4
+
5
+ =============================================================================
6
+ HOW TO ADD A NEW AI TOOL TO JACQUES
7
+ =============================================================================
8
+
9
+ This template shows how to create an adapter for a new AI tool.
10
+ Follow these steps to add support for a new source:
11
+
12
+ 1. COPY this file and rename it (e.g., 'vscode.py')
13
+ 2. UPDATE the class name and source property
14
+ 3. IMPLEMENT the required methods:
15
+ - get_session_id(): Map your tool's session identifier field
16
+ - get_project_path(): Map your tool's project path field
17
+ 4. CREATE hook scripts in hooks/{your-source}/
18
+ 5. UPDATE hooks/adapters/__init__.py to export your adapter
19
+ 6. ADD installation support in hooks/install.py
20
+
21
+ =============================================================================
22
+ FIELD MAPPING REFERENCE
23
+ =============================================================================
24
+
25
+ Different AI tools use different field names. Here's how existing tools map:
26
+
27
+ | Concept | Claude Code CLI | Cursor Native | Your Tool |
28
+ |-----------------|---------------------|----------------------|---------------|
29
+ | Session ID | session_id | conversation_id | ??? |
30
+ | Project Path | workspace.project_dir| workspace_roots[0] | ??? |
31
+ | Model Name | model | model_name | ??? |
32
+ | Transcript | transcript_path | (none) | ??? |
33
+ | Context % | statusLine event | preCompact event | ??? |
34
+
35
+ =============================================================================
36
+ """
37
+ from typing import Optional
38
+ from .base import BaseAdapter
39
+
40
+
41
+ class TemplateAdapter(BaseAdapter):
42
+ """
43
+ Template adapter for a new AI tool.
44
+
45
+ Replace 'template' with your tool name (e.g., 'vscode', 'windsurf').
46
+ """
47
+
48
+ @property
49
+ def source(self) -> str:
50
+ """
51
+ REQUIRED: Unique identifier for this source.
52
+
53
+ This appears in the Jacques dashboard and is used for filtering.
54
+ Examples: 'claude_code', 'cursor', 'vscode', 'windsurf'
55
+ """
56
+ return 'template' # TODO: Change this!
57
+
58
+ def get_session_id(self, input_data: dict) -> Optional[str]:
59
+ """
60
+ REQUIRED: Extract session ID from your tool's input format.
61
+
62
+ Find out what field your tool uses for the session/conversation ID
63
+ and extract it here.
64
+
65
+ Examples:
66
+ - Claude Code: input_data.get('session_id')
67
+ - Cursor: input_data.get('conversation_id')
68
+ """
69
+ # TODO: Implement for your tool
70
+ return input_data.get('session_id')
71
+
72
+ def get_project_path(self, input_data: dict) -> Optional[str]:
73
+ """
74
+ REQUIRED: Extract project path from your tool's input format.
75
+
76
+ Find out what field your tool uses for the workspace/project path
77
+ and extract it here.
78
+
79
+ Examples:
80
+ - Claude Code: input_data.get('workspace', {}).get('project_dir')
81
+ - Cursor: input_data.get('workspace_roots', [])[0]
82
+ """
83
+ # TODO: Implement for your tool
84
+ return input_data.get('project_path', '')
85
+
86
+ # =========================================================================
87
+ # HOOK METHODS - Implement based on your tool's available hooks
88
+ # =========================================================================
89
+
90
+ def build_session_start_payload(self, input_data: dict) -> Optional[dict]:
91
+ """
92
+ Build payload for session_start event.
93
+
94
+ This is called when a new AI session begins.
95
+
96
+ Typical hook names:
97
+ - Claude Code: SessionStart
98
+ - Cursor: sessionStart
99
+ """
100
+ session_id = self.validate_session_id(input_data)
101
+ if not session_id:
102
+ return None
103
+
104
+ project_info = self.extract_project_info(input_data)
105
+
106
+ # Try to extract session title (if your tool supports transcripts)
107
+ transcript_path = input_data.get('transcript_path')
108
+ session_title = self.extract_session_title(transcript_path)
109
+ if not session_title:
110
+ session_title = self.generate_fallback_title(project_info['project'])
111
+
112
+ terminal = self.get_terminal_identity()
113
+ terminal_key = self.build_terminal_key(terminal)
114
+
115
+ return self.build_base_payload(
116
+ event='session_start',
117
+ session_id=session_id,
118
+ session_title=session_title,
119
+ transcript_path=transcript_path,
120
+ cwd=project_info['cwd'],
121
+ project=project_info['project'],
122
+ project_dir=project_info['project_path'],
123
+ model=input_data.get('model'),
124
+ hook_source='startup',
125
+ terminal=terminal,
126
+ terminal_key=terminal_key,
127
+ )
128
+
129
+ def build_activity_payload(self, input_data: dict) -> Optional[dict]:
130
+ """
131
+ Build payload for activity event.
132
+
133
+ This is called when the AI uses a tool or takes an action.
134
+
135
+ Typical hook names:
136
+ - Claude Code: PostToolUse
137
+ - Cursor: postToolUse
138
+ """
139
+ session_id = self.validate_session_id(input_data)
140
+ if not session_id:
141
+ return None
142
+
143
+ project_info = self.extract_project_info(input_data)
144
+ session_title = self.generate_fallback_title(project_info['project'])
145
+
146
+ return self.build_base_payload(
147
+ event='activity',
148
+ session_id=session_id,
149
+ session_title=session_title,
150
+ tool_name=input_data.get('tool_name', 'unknown'),
151
+ terminal_pid=self.get_terminal_identity()['terminal_pid'],
152
+ )
153
+
154
+ def build_idle_payload(self, input_data: dict) -> Optional[dict]:
155
+ """
156
+ Build payload for idle event.
157
+
158
+ This is called when the AI is waiting for user input.
159
+
160
+ Typical hook names:
161
+ - Claude Code: Stop
162
+ - Cursor: (may not have equivalent)
163
+ """
164
+ session_id = self.validate_session_id(input_data)
165
+ if not session_id:
166
+ return None
167
+
168
+ return self.build_base_payload(
169
+ event='idle',
170
+ session_id=session_id,
171
+ terminal_pid=self.get_terminal_identity()['terminal_pid'],
172
+ )
173
+
174
+ def build_session_end_payload(self, input_data: dict) -> Optional[dict]:
175
+ """
176
+ Build payload for session_end event.
177
+
178
+ This is called when an AI session ends.
179
+
180
+ Typical hook names:
181
+ - Claude Code: SessionEnd
182
+ - Cursor: sessionEnd
183
+ """
184
+ session_id = self.validate_session_id(input_data)
185
+ if not session_id:
186
+ return None
187
+
188
+ return self.build_base_payload(
189
+ event='session_end',
190
+ session_id=session_id,
191
+ terminal_pid=self.get_terminal_identity()['terminal_pid'],
192
+ )
193
+
194
+ def build_context_update_payload(self, input_data: dict) -> Optional[dict]:
195
+ """
196
+ Build payload for context_update event.
197
+
198
+ OPTIONAL: Only implement if your tool provides context metrics.
199
+
200
+ This provides real-time context window usage data.
201
+
202
+ Typical sources:
203
+ - Claude Code: statusLine (shell script, not Python hook)
204
+ - Cursor: preCompact event
205
+
206
+ If your tool doesn't provide context metrics, Jacques will show
207
+ "N/A" for context percentage, which is fine.
208
+ """
209
+ session_id = self.validate_session_id(input_data)
210
+ if not session_id:
211
+ return None
212
+
213
+ # TODO: Map your tool's context metric fields
214
+ # Example fields you might find:
215
+ # - context_usage_percent / used_percentage
216
+ # - context_tokens / total_tokens
217
+ # - context_window_size / max_tokens
218
+
219
+ used_percentage = input_data.get('used_percentage', 0)
220
+ remaining_percentage = 100 - used_percentage
221
+
222
+ project_info = self.extract_project_info(input_data)
223
+
224
+ return self.build_base_payload(
225
+ event='context_update',
226
+ session_id=session_id,
227
+ used_percentage=used_percentage,
228
+ remaining_percentage=remaining_percentage,
229
+ context_window_size=input_data.get('context_window_size', 0),
230
+ total_input_tokens=input_data.get('total_input_tokens', 0),
231
+ total_output_tokens=input_data.get('total_output_tokens', 0),
232
+ model=input_data.get('model', 'unknown'),
233
+ model_display_name=input_data.get('model_display_name', 'Unknown'),
234
+ cwd=project_info['cwd'],
235
+ project_dir=project_info['project_path'],
236
+ )
237
+
238
+
239
+ # =============================================================================
240
+ # EXAMPLE HOOK SCRIPT
241
+ # =============================================================================
242
+ #
243
+ # Create a file in hooks/{your-source}/session-start.py:
244
+ #
245
+ # #!/usr/bin/env python3
246
+ # """Session start hook for {YourTool}."""
247
+ # import sys
248
+ # sys.path.insert(0, str(Path(__file__).parent.parent))
249
+ # from adapters.template import TemplateAdapter # Change to your adapter
250
+ #
251
+ # def main():
252
+ # adapter = TemplateAdapter() # Change to your adapter
253
+ # input_data = adapter.parse_input()
254
+ # if not input_data:
255
+ # sys.exit(0)
256
+ #
257
+ # adapter.log_debug(input_data, 'session-start')
258
+ # payload = adapter.build_session_start_payload(input_data)
259
+ # if payload:
260
+ # adapter.send_event(payload, use_fallback=True)
261
+ #
262
+ # if __name__ == '__main__':
263
+ # main()
264
+ #
265
+ # =============================================================================
266
+ # TESTING YOUR ADAPTER
267
+ # =============================================================================
268
+ #
269
+ # 1. Start Jacques server:
270
+ # cd server && npm run start
271
+ #
272
+ # 2. Test with sample input:
273
+ # echo '{"session_id": "test-123", "project_path": "/my/project"}' | \
274
+ # python3 hooks/{your-source}/session-start.py
275
+ #
276
+ # 3. Check server logs or dashboard for the session
277
+ #
278
+ # 4. Run unit tests:
279
+ # python3 -m pytest hooks/adapters/test_adapters.py -v
280
+ #
281
+ # =============================================================================