@useconductor/conductor 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 (504) hide show
  1. package/.claude-plugin/marketplace.json +33 -0
  2. package/.claude-plugin/plugin.json +23 -0
  3. package/.eslintrc.json +23 -0
  4. package/.gitattributes +6 -0
  5. package/.github/FUNDING.yml +15 -0
  6. package/.github/ISSUE_TEMPLATE/bug_report.yml +91 -0
  7. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  8. package/.github/ISSUE_TEMPLATE/feature_request.yml +63 -0
  9. package/.github/ISSUE_TEMPLATE/plugin_request.yml +71 -0
  10. package/.github/README.md +13 -0
  11. package/.github/workflows/README.md +22 -0
  12. package/.github/workflows/auto-release.yml +112 -0
  13. package/.github/workflows/ci.yml +49 -0
  14. package/.github/workflows/claude-code-review.yml +44 -0
  15. package/.github/workflows/claude.yml +36 -0
  16. package/.github/workflows/sync-install.yml +47 -0
  17. package/.mcp.json +9 -0
  18. package/.prettierrc.json +7 -0
  19. package/C.png +0 -0
  20. package/CHANGELOG.md +74 -0
  21. package/CLAUDE.md +118 -0
  22. package/CONTRIBUTING.md +231 -0
  23. package/LICENSE +201 -0
  24. package/README.md +179 -0
  25. package/SECURITY.md +47 -0
  26. package/commands/conductor-setup.md +11 -0
  27. package/commands/conductor-status.md +7 -0
  28. package/dist/ai/base.d.ts +44 -0
  29. package/dist/ai/base.d.ts.map +1 -0
  30. package/dist/ai/base.js +47 -0
  31. package/dist/ai/base.js.map +1 -0
  32. package/dist/ai/claude.d.ts +11 -0
  33. package/dist/ai/claude.d.ts.map +1 -0
  34. package/dist/ai/claude.js +149 -0
  35. package/dist/ai/claude.js.map +1 -0
  36. package/dist/ai/gemini.d.ts +15 -0
  37. package/dist/ai/gemini.d.ts.map +1 -0
  38. package/dist/ai/gemini.js +156 -0
  39. package/dist/ai/gemini.js.map +1 -0
  40. package/dist/ai/maestro.d.ts +22 -0
  41. package/dist/ai/maestro.d.ts.map +1 -0
  42. package/dist/ai/maestro.js +142 -0
  43. package/dist/ai/maestro.js.map +1 -0
  44. package/dist/ai/manager.d.ts +47 -0
  45. package/dist/ai/manager.d.ts.map +1 -0
  46. package/dist/ai/manager.js +450 -0
  47. package/dist/ai/manager.js.map +1 -0
  48. package/dist/ai/ollama.d.ts +16 -0
  49. package/dist/ai/ollama.d.ts.map +1 -0
  50. package/dist/ai/ollama.js +151 -0
  51. package/dist/ai/ollama.js.map +1 -0
  52. package/dist/ai/openai.d.ts +11 -0
  53. package/dist/ai/openai.d.ts.map +1 -0
  54. package/dist/ai/openai.js +132 -0
  55. package/dist/ai/openai.js.map +1 -0
  56. package/dist/ai/openrouter.d.ts +11 -0
  57. package/dist/ai/openrouter.d.ts.map +1 -0
  58. package/dist/ai/openrouter.js +139 -0
  59. package/dist/ai/openrouter.js.map +1 -0
  60. package/dist/bot/slack.d.ts +17 -0
  61. package/dist/bot/slack.d.ts.map +1 -0
  62. package/dist/bot/slack.js +144 -0
  63. package/dist/bot/slack.js.map +1 -0
  64. package/dist/bot/telegram.d.ts +19 -0
  65. package/dist/bot/telegram.d.ts.map +1 -0
  66. package/dist/bot/telegram.js +157 -0
  67. package/dist/bot/telegram.js.map +1 -0
  68. package/dist/cli/commands/ai.d.ts +4 -0
  69. package/dist/cli/commands/ai.d.ts.map +1 -0
  70. package/dist/cli/commands/ai.js +161 -0
  71. package/dist/cli/commands/ai.js.map +1 -0
  72. package/dist/cli/commands/doctor.d.ts +18 -0
  73. package/dist/cli/commands/doctor.d.ts.map +1 -0
  74. package/dist/cli/commands/doctor.js +213 -0
  75. package/dist/cli/commands/doctor.js.map +1 -0
  76. package/dist/cli/commands/init.d.ts +15 -0
  77. package/dist/cli/commands/init.d.ts.map +1 -0
  78. package/dist/cli/commands/init.js +281 -0
  79. package/dist/cli/commands/init.js.map +1 -0
  80. package/dist/cli/commands/install.d.ts +16 -0
  81. package/dist/cli/commands/install.d.ts.map +1 -0
  82. package/dist/cli/commands/install.js +750 -0
  83. package/dist/cli/commands/install.js.map +1 -0
  84. package/dist/cli/commands/lifecycle.d.ts +4 -0
  85. package/dist/cli/commands/lifecycle.d.ts.map +1 -0
  86. package/dist/cli/commands/lifecycle.js +84 -0
  87. package/dist/cli/commands/lifecycle.js.map +1 -0
  88. package/dist/cli/commands/marketplace.d.ts +13 -0
  89. package/dist/cli/commands/marketplace.d.ts.map +1 -0
  90. package/dist/cli/commands/marketplace.js +197 -0
  91. package/dist/cli/commands/marketplace.js.map +1 -0
  92. package/dist/cli/commands/mcp.d.ts +6 -0
  93. package/dist/cli/commands/mcp.d.ts.map +1 -0
  94. package/dist/cli/commands/mcp.js +83 -0
  95. package/dist/cli/commands/mcp.js.map +1 -0
  96. package/dist/cli/commands/onboard.d.ts +10 -0
  97. package/dist/cli/commands/onboard.d.ts.map +1 -0
  98. package/dist/cli/commands/onboard.js +207 -0
  99. package/dist/cli/commands/onboard.js.map +1 -0
  100. package/dist/cli/commands/plugin-create.d.ts +13 -0
  101. package/dist/cli/commands/plugin-create.d.ts.map +1 -0
  102. package/dist/cli/commands/plugin-create.js +122 -0
  103. package/dist/cli/commands/plugin-create.js.map +1 -0
  104. package/dist/cli/commands/plugins.d.ts +5 -0
  105. package/dist/cli/commands/plugins.d.ts.map +1 -0
  106. package/dist/cli/commands/plugins.js +30 -0
  107. package/dist/cli/commands/plugins.js.map +1 -0
  108. package/dist/cli/commands/release.d.ts +13 -0
  109. package/dist/cli/commands/release.d.ts.map +1 -0
  110. package/dist/cli/commands/release.js +243 -0
  111. package/dist/cli/commands/release.js.map +1 -0
  112. package/dist/cli/commands/telegram.d.ts +3 -0
  113. package/dist/cli/commands/telegram.d.ts.map +1 -0
  114. package/dist/cli/commands/telegram.js +20 -0
  115. package/dist/cli/commands/telegram.js.map +1 -0
  116. package/dist/cli/index.d.ts +3 -0
  117. package/dist/cli/index.d.ts.map +1 -0
  118. package/dist/cli/index.js +402 -0
  119. package/dist/cli/index.js.map +1 -0
  120. package/dist/config/oauth.d.ts +8 -0
  121. package/dist/config/oauth.d.ts.map +1 -0
  122. package/dist/config/oauth.js +13 -0
  123. package/dist/config/oauth.js.map +1 -0
  124. package/dist/core/audit.d.ts +91 -0
  125. package/dist/core/audit.d.ts.map +1 -0
  126. package/dist/core/audit.js +233 -0
  127. package/dist/core/audit.js.map +1 -0
  128. package/dist/core/circuit-breaker.d.ts +56 -0
  129. package/dist/core/circuit-breaker.d.ts.map +1 -0
  130. package/dist/core/circuit-breaker.js +107 -0
  131. package/dist/core/circuit-breaker.js.map +1 -0
  132. package/dist/core/conductor.d.ts +44 -0
  133. package/dist/core/conductor.d.ts.map +1 -0
  134. package/dist/core/conductor.js +200 -0
  135. package/dist/core/conductor.js.map +1 -0
  136. package/dist/core/config.d.ts +66 -0
  137. package/dist/core/config.d.ts.map +1 -0
  138. package/dist/core/config.js +86 -0
  139. package/dist/core/config.js.map +1 -0
  140. package/dist/core/database.d.ts +59 -0
  141. package/dist/core/database.d.ts.map +1 -0
  142. package/dist/core/database.js +342 -0
  143. package/dist/core/database.js.map +1 -0
  144. package/dist/core/errors.d.ts +231 -0
  145. package/dist/core/errors.d.ts.map +1 -0
  146. package/dist/core/errors.js +254 -0
  147. package/dist/core/errors.js.map +1 -0
  148. package/dist/core/health.d.ts +72 -0
  149. package/dist/core/health.d.ts.map +1 -0
  150. package/dist/core/health.js +116 -0
  151. package/dist/core/health.js.map +1 -0
  152. package/dist/core/interfaces.d.ts +62 -0
  153. package/dist/core/interfaces.d.ts.map +1 -0
  154. package/dist/core/interfaces.js +8 -0
  155. package/dist/core/interfaces.js.map +1 -0
  156. package/dist/core/logger.d.ts +15 -0
  157. package/dist/core/logger.d.ts.map +1 -0
  158. package/dist/core/logger.js +30 -0
  159. package/dist/core/logger.js.map +1 -0
  160. package/dist/core/rbac.d.ts +132 -0
  161. package/dist/core/rbac.d.ts.map +1 -0
  162. package/dist/core/rbac.js +230 -0
  163. package/dist/core/rbac.js.map +1 -0
  164. package/dist/core/retry.d.ts +22 -0
  165. package/dist/core/retry.d.ts.map +1 -0
  166. package/dist/core/retry.js +41 -0
  167. package/dist/core/retry.js.map +1 -0
  168. package/dist/core/webhooks.d.ts +92 -0
  169. package/dist/core/webhooks.d.ts.map +1 -0
  170. package/dist/core/webhooks.js +176 -0
  171. package/dist/core/webhooks.js.map +1 -0
  172. package/dist/core/zero-config.d.ts +22 -0
  173. package/dist/core/zero-config.d.ts.map +1 -0
  174. package/dist/core/zero-config.js +59 -0
  175. package/dist/core/zero-config.js.map +1 -0
  176. package/dist/dashboard/cli.d.ts +6 -0
  177. package/dist/dashboard/cli.d.ts.map +1 -0
  178. package/dist/dashboard/cli.js +42 -0
  179. package/dist/dashboard/cli.js.map +1 -0
  180. package/dist/dashboard/index.html +3426 -0
  181. package/dist/dashboard/server.d.ts +7 -0
  182. package/dist/dashboard/server.d.ts.map +1 -0
  183. package/dist/dashboard/server.js +1427 -0
  184. package/dist/dashboard/server.js.map +1 -0
  185. package/dist/mcp/server.d.ts +27 -0
  186. package/dist/mcp/server.d.ts.map +1 -0
  187. package/dist/mcp/server.js +380 -0
  188. package/dist/mcp/server.js.map +1 -0
  189. package/dist/mcp/tools/misc.d.ts +15 -0
  190. package/dist/mcp/tools/misc.d.ts.map +1 -0
  191. package/dist/mcp/tools/misc.js +49 -0
  192. package/dist/mcp/tools/misc.js.map +1 -0
  193. package/dist/plugins/builtin/calculator.d.ts +11 -0
  194. package/dist/plugins/builtin/calculator.d.ts.map +1 -0
  195. package/dist/plugins/builtin/calculator.js +166 -0
  196. package/dist/plugins/builtin/calculator.js.map +1 -0
  197. package/dist/plugins/builtin/colors.d.ts +15 -0
  198. package/dist/plugins/builtin/colors.d.ts.map +1 -0
  199. package/dist/plugins/builtin/colors.js +193 -0
  200. package/dist/plugins/builtin/colors.js.map +1 -0
  201. package/dist/plugins/builtin/cron.d.ts +40 -0
  202. package/dist/plugins/builtin/cron.d.ts.map +1 -0
  203. package/dist/plugins/builtin/cron.js +578 -0
  204. package/dist/plugins/builtin/cron.js.map +1 -0
  205. package/dist/plugins/builtin/crypto.d.ts +11 -0
  206. package/dist/plugins/builtin/crypto.d.ts.map +1 -0
  207. package/dist/plugins/builtin/crypto.js +83 -0
  208. package/dist/plugins/builtin/crypto.js.map +1 -0
  209. package/dist/plugins/builtin/database.d.ts +29 -0
  210. package/dist/plugins/builtin/database.d.ts.map +1 -0
  211. package/dist/plugins/builtin/database.js +230 -0
  212. package/dist/plugins/builtin/database.js.map +1 -0
  213. package/dist/plugins/builtin/docker.d.ts +12 -0
  214. package/dist/plugins/builtin/docker.d.ts.map +1 -0
  215. package/dist/plugins/builtin/docker.js +436 -0
  216. package/dist/plugins/builtin/docker.js.map +1 -0
  217. package/dist/plugins/builtin/fun.d.ts +11 -0
  218. package/dist/plugins/builtin/fun.d.ts.map +1 -0
  219. package/dist/plugins/builtin/fun.js +114 -0
  220. package/dist/plugins/builtin/fun.js.map +1 -0
  221. package/dist/plugins/builtin/gcal.d.ts +38 -0
  222. package/dist/plugins/builtin/gcal.d.ts.map +1 -0
  223. package/dist/plugins/builtin/gcal.js +280 -0
  224. package/dist/plugins/builtin/gcal.js.map +1 -0
  225. package/dist/plugins/builtin/gdrive.d.ts +26 -0
  226. package/dist/plugins/builtin/gdrive.d.ts.map +1 -0
  227. package/dist/plugins/builtin/gdrive.js +295 -0
  228. package/dist/plugins/builtin/gdrive.js.map +1 -0
  229. package/dist/plugins/builtin/github-actions.d.ts +38 -0
  230. package/dist/plugins/builtin/github-actions.d.ts.map +1 -0
  231. package/dist/plugins/builtin/github-actions.js +629 -0
  232. package/dist/plugins/builtin/github-actions.js.map +1 -0
  233. package/dist/plugins/builtin/github.d.ts +26 -0
  234. package/dist/plugins/builtin/github.d.ts.map +1 -0
  235. package/dist/plugins/builtin/github.js +800 -0
  236. package/dist/plugins/builtin/github.js.map +1 -0
  237. package/dist/plugins/builtin/gmail.d.ts +50 -0
  238. package/dist/plugins/builtin/gmail.d.ts.map +1 -0
  239. package/dist/plugins/builtin/gmail.js +445 -0
  240. package/dist/plugins/builtin/gmail.js.map +1 -0
  241. package/dist/plugins/builtin/hash.d.ts +11 -0
  242. package/dist/plugins/builtin/hash.d.ts.map +1 -0
  243. package/dist/plugins/builtin/hash.js +95 -0
  244. package/dist/plugins/builtin/hash.js.map +1 -0
  245. package/dist/plugins/builtin/homekit.d.ts +53 -0
  246. package/dist/plugins/builtin/homekit.d.ts.map +1 -0
  247. package/dist/plugins/builtin/homekit.js +341 -0
  248. package/dist/plugins/builtin/homekit.js.map +1 -0
  249. package/dist/plugins/builtin/index.d.ts +4 -0
  250. package/dist/plugins/builtin/index.d.ts.map +1 -0
  251. package/dist/plugins/builtin/index.js +96 -0
  252. package/dist/plugins/builtin/index.js.map +1 -0
  253. package/dist/plugins/builtin/jira.d.ts +50 -0
  254. package/dist/plugins/builtin/jira.d.ts.map +1 -0
  255. package/dist/plugins/builtin/jira.js +353 -0
  256. package/dist/plugins/builtin/jira.js.map +1 -0
  257. package/dist/plugins/builtin/linear.d.ts +35 -0
  258. package/dist/plugins/builtin/linear.d.ts.map +1 -0
  259. package/dist/plugins/builtin/linear.js +397 -0
  260. package/dist/plugins/builtin/linear.js.map +1 -0
  261. package/dist/plugins/builtin/lumen.d.ts +21 -0
  262. package/dist/plugins/builtin/lumen.d.ts.map +1 -0
  263. package/dist/plugins/builtin/lumen.js +404 -0
  264. package/dist/plugins/builtin/lumen.js.map +1 -0
  265. package/dist/plugins/builtin/memory.d.ts +22 -0
  266. package/dist/plugins/builtin/memory.d.ts.map +1 -0
  267. package/dist/plugins/builtin/memory.js +184 -0
  268. package/dist/plugins/builtin/memory.js.map +1 -0
  269. package/dist/plugins/builtin/n8n.d.ts +60 -0
  270. package/dist/plugins/builtin/n8n.d.ts.map +1 -0
  271. package/dist/plugins/builtin/n8n.js +519 -0
  272. package/dist/plugins/builtin/n8n.js.map +1 -0
  273. package/dist/plugins/builtin/network.d.ts +11 -0
  274. package/dist/plugins/builtin/network.d.ts.map +1 -0
  275. package/dist/plugins/builtin/network.js +88 -0
  276. package/dist/plugins/builtin/network.js.map +1 -0
  277. package/dist/plugins/builtin/notes.d.ts +47 -0
  278. package/dist/plugins/builtin/notes.d.ts.map +1 -0
  279. package/dist/plugins/builtin/notes.js +641 -0
  280. package/dist/plugins/builtin/notes.js.map +1 -0
  281. package/dist/plugins/builtin/notion.d.ts +47 -0
  282. package/dist/plugins/builtin/notion.d.ts.map +1 -0
  283. package/dist/plugins/builtin/notion.js +317 -0
  284. package/dist/plugins/builtin/notion.js.map +1 -0
  285. package/dist/plugins/builtin/shell.d.ts +12 -0
  286. package/dist/plugins/builtin/shell.d.ts.map +1 -0
  287. package/dist/plugins/builtin/shell.js +310 -0
  288. package/dist/plugins/builtin/shell.js.map +1 -0
  289. package/dist/plugins/builtin/slack.d.ts +31 -0
  290. package/dist/plugins/builtin/slack.d.ts.map +1 -0
  291. package/dist/plugins/builtin/slack.js +295 -0
  292. package/dist/plugins/builtin/slack.js.map +1 -0
  293. package/dist/plugins/builtin/spotify.d.ts +55 -0
  294. package/dist/plugins/builtin/spotify.d.ts.map +1 -0
  295. package/dist/plugins/builtin/spotify.js +623 -0
  296. package/dist/plugins/builtin/spotify.js.map +1 -0
  297. package/dist/plugins/builtin/stripe.d.ts +35 -0
  298. package/dist/plugins/builtin/stripe.d.ts.map +1 -0
  299. package/dist/plugins/builtin/stripe.js +376 -0
  300. package/dist/plugins/builtin/stripe.js.map +1 -0
  301. package/dist/plugins/builtin/system.d.ts +11 -0
  302. package/dist/plugins/builtin/system.d.ts.map +1 -0
  303. package/dist/plugins/builtin/system.js +91 -0
  304. package/dist/plugins/builtin/system.js.map +1 -0
  305. package/dist/plugins/builtin/text-tools.d.ts +11 -0
  306. package/dist/plugins/builtin/text-tools.d.ts.map +1 -0
  307. package/dist/plugins/builtin/text-tools.js +146 -0
  308. package/dist/plugins/builtin/text-tools.js.map +1 -0
  309. package/dist/plugins/builtin/timezone.d.ts +13 -0
  310. package/dist/plugins/builtin/timezone.d.ts.map +1 -0
  311. package/dist/plugins/builtin/timezone.js +164 -0
  312. package/dist/plugins/builtin/timezone.js.map +1 -0
  313. package/dist/plugins/builtin/todoist.d.ts +49 -0
  314. package/dist/plugins/builtin/todoist.d.ts.map +1 -0
  315. package/dist/plugins/builtin/todoist.js +540 -0
  316. package/dist/plugins/builtin/todoist.js.map +1 -0
  317. package/dist/plugins/builtin/translate.d.ts +11 -0
  318. package/dist/plugins/builtin/translate.d.ts.map +1 -0
  319. package/dist/plugins/builtin/translate.js +42 -0
  320. package/dist/plugins/builtin/translate.js.map +1 -0
  321. package/dist/plugins/builtin/url-tools.d.ts +11 -0
  322. package/dist/plugins/builtin/url-tools.d.ts.map +1 -0
  323. package/dist/plugins/builtin/url-tools.js +70 -0
  324. package/dist/plugins/builtin/url-tools.js.map +1 -0
  325. package/dist/plugins/builtin/vercel.d.ts +55 -0
  326. package/dist/plugins/builtin/vercel.d.ts.map +1 -0
  327. package/dist/plugins/builtin/vercel.js +514 -0
  328. package/dist/plugins/builtin/vercel.js.map +1 -0
  329. package/dist/plugins/builtin/weather.d.ts +13 -0
  330. package/dist/plugins/builtin/weather.d.ts.map +1 -0
  331. package/dist/plugins/builtin/weather.js +103 -0
  332. package/dist/plugins/builtin/weather.js.map +1 -0
  333. package/dist/plugins/builtin/x.d.ts +54 -0
  334. package/dist/plugins/builtin/x.d.ts.map +1 -0
  335. package/dist/plugins/builtin/x.js +402 -0
  336. package/dist/plugins/builtin/x.js.map +1 -0
  337. package/dist/plugins/manager.d.ts +77 -0
  338. package/dist/plugins/manager.d.ts.map +1 -0
  339. package/dist/plugins/manager.js +141 -0
  340. package/dist/plugins/manager.js.map +1 -0
  341. package/dist/plugins/validation.d.ts +18 -0
  342. package/dist/plugins/validation.d.ts.map +1 -0
  343. package/dist/plugins/validation.js +81 -0
  344. package/dist/plugins/validation.js.map +1 -0
  345. package/dist/security/auth.d.ts +23 -0
  346. package/dist/security/auth.d.ts.map +1 -0
  347. package/dist/security/auth.js +56 -0
  348. package/dist/security/auth.js.map +1 -0
  349. package/dist/security/keychain.d.ts +60 -0
  350. package/dist/security/keychain.d.ts.map +1 -0
  351. package/dist/security/keychain.js +213 -0
  352. package/dist/security/keychain.js.map +1 -0
  353. package/dist/utils/google-auth.d.ts +21 -0
  354. package/dist/utils/google-auth.d.ts.map +1 -0
  355. package/dist/utils/google-auth.js +135 -0
  356. package/dist/utils/google-auth.js.map +1 -0
  357. package/dist/utils/retry.d.ts +5 -0
  358. package/dist/utils/retry.d.ts.map +1 -0
  359. package/dist/utils/retry.js +34 -0
  360. package/dist/utils/retry.js.map +1 -0
  361. package/docs/README.md +13 -0
  362. package/docs/api.md +210 -0
  363. package/docs/getting-started.md +100 -0
  364. package/docs/plugins.md +306 -0
  365. package/docs-site/.vitepress/config.ts +59 -0
  366. package/docs-site/README.md +12 -0
  367. package/docs-site/index.md +30 -0
  368. package/eslint.config.js +29 -0
  369. package/install.ps1 +334 -0
  370. package/install.sh +1119 -0
  371. package/local-install.sh +304 -0
  372. package/package.json +90 -0
  373. package/packages/README.md +11 -0
  374. package/packages/plugin-sdk/README.md +12 -0
  375. package/packages/plugin-sdk/package.json +22 -0
  376. package/packages/plugin-sdk/src/README.md +11 -0
  377. package/packages/plugin-sdk/src/index.ts +191 -0
  378. package/sdks/README.md +26 -0
  379. package/sdks/csharp/ConductorClient.cs +65 -0
  380. package/sdks/csharp/README.md +11 -0
  381. package/sdks/go/README.md +11 -0
  382. package/sdks/go/conductor.go +257 -0
  383. package/sdks/java/ConductorClient.java +27 -0
  384. package/sdks/java/README.md +11 -0
  385. package/sdks/php/README.md +11 -0
  386. package/sdks/php/src/Client.php +72 -0
  387. package/sdks/python/README.md +12 -0
  388. package/sdks/python/conductor/__init__.py +227 -0
  389. package/sdks/python/pyproject.toml +30 -0
  390. package/sdks/ruby/README.md +11 -0
  391. package/sdks/ruby/lib/conductor.rb +46 -0
  392. package/sdks/rust/Cargo.toml +14 -0
  393. package/sdks/rust/README.md +11 -0
  394. package/sdks/swift/README.md +11 -0
  395. package/sdks/swift/Sources/Conductor/ConductorClient.swift +65 -0
  396. package/skills/conductor-mcp/SKILL.md +38 -0
  397. package/src/README.md +20 -0
  398. package/src/ai/README.md +18 -0
  399. package/src/ai/base.ts +93 -0
  400. package/src/ai/claude.ts +162 -0
  401. package/src/ai/gemini.ts +188 -0
  402. package/src/ai/maestro.ts +168 -0
  403. package/src/ai/manager.ts +537 -0
  404. package/src/ai/ollama.ts +186 -0
  405. package/src/ai/openai.ts +147 -0
  406. package/src/ai/openrouter.ts +152 -0
  407. package/src/bot/README.md +12 -0
  408. package/src/bot/slack.ts +164 -0
  409. package/src/bot/telegram.ts +185 -0
  410. package/src/cli/README.md +24 -0
  411. package/src/cli/commands/README.md +20 -0
  412. package/src/cli/commands/ai.ts +170 -0
  413. package/src/cli/commands/doctor.ts +221 -0
  414. package/src/cli/commands/init.ts +348 -0
  415. package/src/cli/commands/install.ts +792 -0
  416. package/src/cli/commands/lifecycle.ts +95 -0
  417. package/src/cli/commands/marketplace.ts +253 -0
  418. package/src/cli/commands/mcp.ts +92 -0
  419. package/src/cli/commands/onboard.ts +248 -0
  420. package/src/cli/commands/plugin-create.ts +130 -0
  421. package/src/cli/commands/plugins.ts +36 -0
  422. package/src/cli/commands/release.ts +251 -0
  423. package/src/cli/commands/telegram.ts +25 -0
  424. package/src/cli/index.ts +450 -0
  425. package/src/config/README.md +11 -0
  426. package/src/config/oauth.ts +26 -0
  427. package/src/core/README.md +22 -0
  428. package/src/core/audit.ts +291 -0
  429. package/src/core/circuit-breaker.ts +129 -0
  430. package/src/core/conductor.ts +240 -0
  431. package/src/core/config.ts +149 -0
  432. package/src/core/database.ts +411 -0
  433. package/src/core/errors.ts +275 -0
  434. package/src/core/health.ts +159 -0
  435. package/src/core/interfaces.ts +75 -0
  436. package/src/core/logger.ts +33 -0
  437. package/src/core/rbac.ts +321 -0
  438. package/src/core/retry.ts +61 -0
  439. package/src/core/webhooks.ts +234 -0
  440. package/src/core/zero-config.ts +72 -0
  441. package/src/dashboard/README.md +15 -0
  442. package/src/dashboard/cli.ts +48 -0
  443. package/src/dashboard/index.html +3426 -0
  444. package/src/dashboard/server.ts +1544 -0
  445. package/src/mcp/README.md +20 -0
  446. package/src/mcp/server.ts +475 -0
  447. package/src/mcp/tools/README.md +11 -0
  448. package/src/mcp/tools/misc.ts +61 -0
  449. package/src/plugins/README.md +28 -0
  450. package/src/plugins/builtin/README.md +23 -0
  451. package/src/plugins/builtin/calculator.ts +178 -0
  452. package/src/plugins/builtin/colors.ts +201 -0
  453. package/src/plugins/builtin/cron.ts +649 -0
  454. package/src/plugins/builtin/crypto.ts +85 -0
  455. package/src/plugins/builtin/database.ts +235 -0
  456. package/src/plugins/builtin/docker.ts +426 -0
  457. package/src/plugins/builtin/fun.ts +118 -0
  458. package/src/plugins/builtin/gcal.ts +305 -0
  459. package/src/plugins/builtin/gdrive.ts +326 -0
  460. package/src/plugins/builtin/github-actions.ts +666 -0
  461. package/src/plugins/builtin/github.ts +912 -0
  462. package/src/plugins/builtin/gmail.ts +492 -0
  463. package/src/plugins/builtin/hash.ts +98 -0
  464. package/src/plugins/builtin/homekit.ts +389 -0
  465. package/src/plugins/builtin/index.ts +116 -0
  466. package/src/plugins/builtin/jira.ts +380 -0
  467. package/src/plugins/builtin/linear.ts +448 -0
  468. package/src/plugins/builtin/lumen.ts +497 -0
  469. package/src/plugins/builtin/memory.ts +200 -0
  470. package/src/plugins/builtin/n8n.ts +565 -0
  471. package/src/plugins/builtin/network.ts +92 -0
  472. package/src/plugins/builtin/notes.ts +689 -0
  473. package/src/plugins/builtin/notion.ts +348 -0
  474. package/src/plugins/builtin/shell.ts +334 -0
  475. package/src/plugins/builtin/slack.ts +327 -0
  476. package/src/plugins/builtin/spotify.ts +665 -0
  477. package/src/plugins/builtin/stripe.ts +388 -0
  478. package/src/plugins/builtin/system.ts +93 -0
  479. package/src/plugins/builtin/text-tools.ts +150 -0
  480. package/src/plugins/builtin/timezone.ts +173 -0
  481. package/src/plugins/builtin/todoist.ts +625 -0
  482. package/src/plugins/builtin/translate.ts +47 -0
  483. package/src/plugins/builtin/url-tools.ts +73 -0
  484. package/src/plugins/builtin/vercel.ts +546 -0
  485. package/src/plugins/builtin/weather.ts +112 -0
  486. package/src/plugins/builtin/x.ts +440 -0
  487. package/src/plugins/manager.ts +213 -0
  488. package/src/plugins/validation.ts +94 -0
  489. package/src/security/README.md +12 -0
  490. package/src/security/auth.ts +72 -0
  491. package/src/security/keychain.ts +226 -0
  492. package/src/utils/README.md +12 -0
  493. package/src/utils/google-auth.ts +159 -0
  494. package/src/utils/retry.ts +41 -0
  495. package/test-all.mjs +1256 -0
  496. package/test.mjs +633 -0
  497. package/tests/README.md +19 -0
  498. package/tests/calculator.test.ts +54 -0
  499. package/tests/docker.test.ts +42 -0
  500. package/tests/load.test.ts +129 -0
  501. package/tests/mcp.test.ts +14 -0
  502. package/tests/shell.test.ts +42 -0
  503. package/tsconfig.json +21 -0
  504. package/vitest.config.ts +14 -0
@@ -0,0 +1,291 @@
1
+ /**
2
+ * Audit Logger — Stripe-grade audit trail for every action.
3
+ *
4
+ * Every tool call, config change, auth event, and plugin lifecycle event
5
+ * is logged with: timestamp, actor, action, resource, result, metadata.
6
+ *
7
+ * Logs are append-only, tamper-evident (SHA-256 chain), and queryable.
8
+ * Designed for SOC 2 compliance from day one.
9
+ */
10
+
11
+ import fs from 'fs/promises';
12
+ import path from 'path';
13
+ import crypto from 'crypto';
14
+
15
+ export interface AuditEntry {
16
+ /** ISO 8601 timestamp */
17
+ timestamp: string;
18
+ /** Who performed the action: user ID, API key ID, or 'system' */
19
+ actor: string;
20
+ /** Action performed: tool_call, config_set, plugin_enable, auth_login, etc. */
21
+ action: string;
22
+ /** Resource affected: tool name, config key, plugin name, etc. */
23
+ resource: string;
24
+ /** Result: success, failure, denied, timeout */
25
+ result: 'success' | 'failure' | 'denied' | 'timeout';
26
+ /** Optional metadata: input, output, error, duration_ms, ip, user_agent */
27
+ metadata: Record<string, unknown>;
28
+ /** SHA-256 of previous entry's hash + this entry's content (tamper-evident chain) */
29
+ hash: string;
30
+ /** Hash of the previous entry (forms a blockchain-like chain) */
31
+ previousHash: string;
32
+ }
33
+
34
+ export class AuditLogger {
35
+ private logDir: string;
36
+ private currentFile: string;
37
+ private lastHash: string;
38
+ private maxFileSize: number;
39
+ private buffer: AuditEntry[];
40
+ private flushTimer: NodeJS.Timeout | null;
41
+
42
+ constructor(configDir: string, options?: { maxFileSizeMB?: number; flushIntervalMs?: number }) {
43
+ this.logDir = path.join(configDir, 'audit');
44
+ this.currentFile = path.join(this.logDir, 'audit.log');
45
+ this.lastHash = '0000000000000000000000000000000000000000000000000000000000000000';
46
+ this.maxFileSize = (options?.maxFileSizeMB ?? 100) * 1024 * 1024;
47
+ this.buffer = [];
48
+ this.flushTimer = null;
49
+
50
+ const flushInterval = options?.flushIntervalMs ?? 1000;
51
+ this.flushTimer = setInterval(() => this.flush().catch(() => {}), flushInterval);
52
+ }
53
+
54
+ /**
55
+ * Log an audit entry. Appends to buffer, flushes periodically.
56
+ */
57
+ async log(entry: Omit<AuditEntry, 'hash' | 'previousHash' | 'timestamp'>): Promise<void> {
58
+ const timestamp = new Date().toISOString();
59
+ const content = JSON.stringify({ ...entry, timestamp, previousHash: '' });
60
+ const hash = crypto
61
+ .createHash('sha256')
62
+ .update(this.lastHash + content)
63
+ .digest('hex');
64
+
65
+ const fullEntry: AuditEntry = {
66
+ ...entry,
67
+ timestamp,
68
+ previousHash: this.lastHash,
69
+ hash,
70
+ };
71
+
72
+ this.buffer.push(fullEntry);
73
+ this.lastHash = hash;
74
+
75
+ // Flush immediately for security-critical events
76
+ if (entry.action === 'auth_login' || entry.action === 'auth_failure' || entry.action === 'config_set') {
77
+ await this.flush();
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Convenience: log a tool call.
83
+ */
84
+ async toolCall(
85
+ actor: string,
86
+ tool: string,
87
+ input: unknown,
88
+ result: 'success' | 'failure' | 'denied' | 'timeout',
89
+ metadata: Record<string, unknown> = {},
90
+ ): Promise<void> {
91
+ await this.log({
92
+ actor,
93
+ action: 'tool_call',
94
+ resource: tool,
95
+ result,
96
+ metadata: { input: this.redactSensitive(input), ...metadata },
97
+ });
98
+ }
99
+
100
+ /**
101
+ * Convenience: log a config change.
102
+ */
103
+ async configChange(actor: string, key: string, oldValue: unknown, newValue: unknown): Promise<void> {
104
+ await this.log({
105
+ actor,
106
+ action: 'config_set',
107
+ resource: key,
108
+ result: 'success',
109
+ metadata: { old_value: this.redactSensitive(oldValue), new_value: this.redactSensitive(newValue) },
110
+ });
111
+ }
112
+
113
+ /**
114
+ * Convenience: log an auth event.
115
+ */
116
+ async authEvent(
117
+ actor: string,
118
+ method: string,
119
+ success: boolean,
120
+ metadata: Record<string, unknown> = {},
121
+ ): Promise<void> {
122
+ await this.log({
123
+ actor,
124
+ action: success ? 'auth_login' : 'auth_failure',
125
+ resource: method,
126
+ result: success ? 'success' : 'failure',
127
+ metadata,
128
+ });
129
+ }
130
+
131
+ /**
132
+ * Convenience: log a plugin lifecycle event.
133
+ */
134
+ async pluginEvent(
135
+ actor: string,
136
+ plugin: string,
137
+ action: 'enable' | 'disable' | 'install' | 'uninstall' | 'update',
138
+ metadata: Record<string, unknown> = {},
139
+ ): Promise<void> {
140
+ await this.log({
141
+ actor,
142
+ action: `plugin_${action}`,
143
+ resource: plugin,
144
+ result: 'success',
145
+ metadata,
146
+ });
147
+ }
148
+
149
+ /**
150
+ * Query audit logs with filters.
151
+ */
152
+ async query(options?: {
153
+ actor?: string;
154
+ action?: string;
155
+ resource?: string;
156
+ result?: string;
157
+ since?: string;
158
+ limit?: number;
159
+ }): Promise<AuditEntry[]> {
160
+ const entries: AuditEntry[] = [];
161
+
162
+ try {
163
+ const files = await fs.readdir(this.logDir);
164
+ const logFiles = files.filter((f) => f.endsWith('.log')).sort();
165
+
166
+ for (const file of logFiles) {
167
+ const content = await fs.readFile(path.join(this.logDir, file), 'utf-8');
168
+ for (const line of content.split('\n').filter((l) => l.trim())) {
169
+ try {
170
+ const entry = JSON.parse(line) as AuditEntry;
171
+ if (options?.actor && entry.actor !== options.actor) continue;
172
+ if (options?.action && entry.action !== options.action) continue;
173
+ if (options?.resource && entry.resource !== options.resource) continue;
174
+ if (options?.result && entry.result !== options.result) continue;
175
+ if (options?.since && entry.timestamp < options.since) continue;
176
+ entries.push(entry);
177
+ } catch {
178
+ // Skip malformed lines
179
+ }
180
+ }
181
+ }
182
+ } catch {
183
+ // No logs yet
184
+ }
185
+
186
+ const limit = options?.limit ?? 1000;
187
+ return entries.slice(-limit);
188
+ }
189
+
190
+ /**
191
+ * Verify the integrity of the audit log chain.
192
+ * Returns true if no tampering detected.
193
+ */
194
+ async verifyIntegrity(): Promise<{ valid: boolean; brokenAt?: string }> {
195
+ try {
196
+ const content = await fs.readFile(this.currentFile, 'utf-8');
197
+ const lines = content.split('\n').filter((l) => l.trim());
198
+ let prevHash = '0000000000000000000000000000000000000000000000000000000000000000';
199
+
200
+ for (const line of lines) {
201
+ const entry = JSON.parse(line) as AuditEntry;
202
+
203
+ // Reconstruct what the hash should be
204
+ const expectedHash = crypto
205
+ .createHash('sha256')
206
+ .update(prevHash + JSON.stringify({ ...entry, previousHash: entry.previousHash }))
207
+ .digest('hex');
208
+
209
+ if (entry.hash !== expectedHash) {
210
+ return { valid: false, brokenAt: entry.timestamp };
211
+ }
212
+
213
+ prevHash = entry.hash;
214
+ }
215
+
216
+ return { valid: true };
217
+ } catch {
218
+ return { valid: true }; // No logs = no tampering
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Flush the buffer to disk.
224
+ */
225
+ async flush(): Promise<void> {
226
+ if (this.buffer.length === 0) return;
227
+
228
+ const entries = [...this.buffer];
229
+ this.buffer = [];
230
+
231
+ try {
232
+ await fs.mkdir(this.logDir, { recursive: true, mode: 0o700 });
233
+
234
+ // Rotate if file is too large
235
+ try {
236
+ const stat = await fs.stat(this.currentFile);
237
+ if (stat.size > this.maxFileSize) {
238
+ const rotated = `${this.currentFile}.${Date.now()}.log`;
239
+ await fs.rename(this.currentFile, rotated);
240
+ }
241
+ } catch {
242
+ // File doesn't exist yet
243
+ }
244
+
245
+ const lines = entries.map((e) => JSON.stringify(e)).join('\n') + '\n';
246
+ await fs.appendFile(this.currentFile, lines, { mode: 0o600 });
247
+ } catch (err) {
248
+ // Put entries back in buffer on failure
249
+ this.buffer.unshift(...entries);
250
+ throw err;
251
+ }
252
+ }
253
+
254
+ /**
255
+ * Close the logger and flush remaining entries.
256
+ */
257
+ async close(): Promise<void> {
258
+ if (this.flushTimer) {
259
+ clearInterval(this.flushTimer);
260
+ this.flushTimer = null;
261
+ }
262
+ await this.flush();
263
+ }
264
+
265
+ /**
266
+ * Redact sensitive values from metadata.
267
+ */
268
+ private redactSensitive(value: unknown): unknown {
269
+ if (typeof value === 'string') {
270
+ // Redact anything that looks like a token, key, or password
271
+ if (/^(ghp_|xoxb_|xapp_|sk-|Bearer |token_|api_key_|password)/i.test(value)) {
272
+ return '[REDACTED]';
273
+ }
274
+ if (value.length > 1000) {
275
+ return `[truncated: ${value.length} chars]`;
276
+ }
277
+ }
278
+ if (typeof value === 'object' && value !== null) {
279
+ const result: Record<string, unknown> = {};
280
+ for (const [k, v] of Object.entries(value)) {
281
+ if (/secret|token|key|password|auth/i.test(k)) {
282
+ result[k] = '[REDACTED]';
283
+ } else {
284
+ result[k] = v;
285
+ }
286
+ }
287
+ return result;
288
+ }
289
+ return value;
290
+ }
291
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Circuit Breaker — prevents cascading failures.
3
+ *
4
+ * When a tool or dependency fails repeatedly, the circuit opens and
5
+ * subsequent calls fail fast without hitting the failing service.
6
+ * After a cooldown period, the circuit half-opens to test recovery.
7
+ *
8
+ * States: CLOSED (normal) → OPEN (failing) → HALF_OPEN (testing) → CLOSED
9
+ */
10
+
11
+ export type CircuitState = 'closed' | 'open' | 'half_open';
12
+
13
+ export interface CircuitBreakerOptions {
14
+ /** Number of failures before opening the circuit */
15
+ failureThreshold: number;
16
+ /** Time in ms before attempting recovery */
17
+ recoveryTimeout: number;
18
+ /** Number of successful calls in half_open to close the circuit */
19
+ successThreshold: number;
20
+ }
21
+
22
+ const DEFAULTS: CircuitBreakerOptions = {
23
+ failureThreshold: 5,
24
+ recoveryTimeout: 60_000,
25
+ successThreshold: 2,
26
+ };
27
+
28
+ export class CircuitBreaker {
29
+ private state: CircuitState = 'closed';
30
+ private failures = 0;
31
+ private successes = 0;
32
+ private lastFailureAt = 0;
33
+ private options: CircuitBreakerOptions;
34
+
35
+ constructor(options?: Partial<CircuitBreakerOptions>) {
36
+ this.options = { ...DEFAULTS, ...options };
37
+ }
38
+
39
+ getState(): CircuitState {
40
+ if (this.state === 'open') {
41
+ // Check if recovery timeout has elapsed
42
+ if (Date.now() - this.lastFailureAt >= this.options.recoveryTimeout) {
43
+ this.state = 'half_open';
44
+ this.successes = 0;
45
+ }
46
+ }
47
+ return this.state;
48
+ }
49
+
50
+ /**
51
+ * Execute a function through the circuit breaker.
52
+ * Throws CircuitOpenError if the circuit is open.
53
+ */
54
+ async execute<T>(fn: () => Promise<T>): Promise<T> {
55
+ const state = this.getState();
56
+
57
+ if (state === 'open') {
58
+ throw new CircuitOpenError('Circuit breaker is open — call rejected');
59
+ }
60
+
61
+ try {
62
+ const result = await fn();
63
+ this.onSuccess();
64
+ return result;
65
+ } catch (err) {
66
+ this.onFailure();
67
+ throw err;
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Record a successful call.
73
+ */
74
+ private onSuccess(): void {
75
+ this.failures = 0;
76
+
77
+ if (this.state === 'half_open') {
78
+ this.successes++;
79
+ if (this.successes >= this.options.successThreshold) {
80
+ this.state = 'closed';
81
+ this.successes = 0;
82
+ }
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Record a failed call.
88
+ */
89
+ private onFailure(): void {
90
+ this.failures++;
91
+ this.lastFailureAt = Date.now();
92
+
93
+ if (this.state === 'half_open') {
94
+ // Any failure in half_open re-opens the circuit
95
+ this.state = 'open';
96
+ this.successes = 0;
97
+ } else if (this.failures >= this.options.failureThreshold) {
98
+ this.state = 'open';
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Reset the circuit breaker to closed state.
104
+ */
105
+ reset(): void {
106
+ this.state = 'closed';
107
+ this.failures = 0;
108
+ this.successes = 0;
109
+ this.lastFailureAt = 0;
110
+ }
111
+
112
+ /**
113
+ * Get circuit breaker status for health checks.
114
+ */
115
+ getStatus(): { state: CircuitState; failures: number; successes: number } {
116
+ return {
117
+ state: this.getState(),
118
+ failures: this.failures,
119
+ successes: this.successes,
120
+ };
121
+ }
122
+ }
123
+
124
+ export class CircuitOpenError extends Error {
125
+ constructor(message: string) {
126
+ super(message);
127
+ this.name = 'CircuitOpenError';
128
+ }
129
+ }
@@ -0,0 +1,240 @@
1
+ import { ConfigManager } from './config.js';
2
+ import { DatabaseManager } from './database.js';
3
+ import { PluginManager } from '../plugins/manager.js';
4
+ import { AIManager } from '../ai/manager.js';
5
+ import type { ConductorNotification } from './interfaces.js';
6
+
7
+ export interface ConductorOptions {
8
+ /** Suppress stdout output (required for MCP mode where stdout is protocol). */
9
+ quiet?: boolean;
10
+ }
11
+
12
+ export class Conductor {
13
+ private config: ConfigManager;
14
+ private db: DatabaseManager;
15
+ private plugins: PluginManager;
16
+ private ai: AIManager;
17
+ private initialized: boolean = false;
18
+ private quiet: boolean;
19
+ private proactiveTimer?: NodeJS.Timeout;
20
+ private notificationHandler?: (notification: ConductorNotification) => Promise<void>;
21
+ /** Prevents overlapping proactive reasoning cycles. */
22
+ private _cycleRunning = false;
23
+
24
+ constructor(configPath?: string, options?: ConductorOptions) {
25
+ this.config = new ConfigManager(configPath);
26
+ this.db = new DatabaseManager(this.config.getConfigDir());
27
+ this.plugins = new PluginManager(this);
28
+ this.ai = new AIManager(this);
29
+ this.quiet = options?.quiet ?? false;
30
+ }
31
+
32
+ async initialize(): Promise<void> {
33
+ if (this.initialized) return;
34
+
35
+ if (!this.quiet) {
36
+ process.stderr.write('Initializing Conductor...\n');
37
+ }
38
+
39
+ await this.config.initialize();
40
+ await this.db.initialize();
41
+ await this.plugins.loadBuiltins();
42
+
43
+ this.initialized = true;
44
+
45
+ await this.db.logActivity('system', 'conductor_initialized');
46
+ }
47
+
48
+ getConfig(): ConfigManager {
49
+ return this.config;
50
+ }
51
+
52
+ getDatabase(): DatabaseManager {
53
+ return this.db;
54
+ }
55
+
56
+ isInitialized(): boolean {
57
+ return this.initialized;
58
+ }
59
+
60
+ async shutdown(): Promise<void> {
61
+ if (this.initialized) {
62
+ await this.db.logActivity('system', 'conductor_shutdown');
63
+ await this.db.close();
64
+ }
65
+ }
66
+
67
+ // Quick access methods
68
+ async getUserInfo() {
69
+ return this.config.get('user');
70
+ }
71
+
72
+ async getTelegramConfig() {
73
+ return this.config.get('telegram');
74
+ }
75
+
76
+ async getAIConfig() {
77
+ return this.config.get('ai');
78
+ }
79
+
80
+ async getPlugins() {
81
+ return this.db.getPlugins();
82
+ }
83
+
84
+ async getRecentActivity(limit: number = 20) {
85
+ return this.db.getRecentActivity(limit);
86
+ }
87
+
88
+ getPluginsManager(): PluginManager {
89
+ return this.plugins;
90
+ }
91
+
92
+ getAIManager(): AIManager {
93
+ return this.ai;
94
+ }
95
+
96
+ /** Set a handler for proactive notifications (e.g. from the heartbeat loop). */
97
+ setNotificationHandler(handler: (notification: ConductorNotification) => Promise<void>): void {
98
+ this.notificationHandler = handler;
99
+ }
100
+
101
+ /** Send a proactive notification to the user via the registered handler. */
102
+ async notifyUser(notification: ConductorNotification): Promise<void> {
103
+ if (this.notificationHandler) {
104
+ await this.notificationHandler(notification);
105
+ } else {
106
+ process.stderr.write(` [Proactive] ${notification.title}: ${notification.body}\n`);
107
+ }
108
+ }
109
+
110
+ /** Start the proactive autonomous loop. */
111
+ async startProactiveMode(intervalMinutes: number = 30): Promise<void> {
112
+ if (this.proactiveTimer) return;
113
+
114
+ if (!this.quiet) {
115
+ process.stderr.write(`Starting proactive mode (every ${intervalMinutes}m)...\n`);
116
+ }
117
+
118
+ // Run once immediately
119
+ this.runReasoningCycle().catch((err) => {
120
+ process.stderr.write(`Proactive cycle error: ${err.message}\n`);
121
+ });
122
+
123
+ this.proactiveTimer = setInterval(
124
+ () => {
125
+ this.runReasoningCycle().catch((err) => {
126
+ process.stderr.write(`Proactive cycle error: ${err.message}\n`);
127
+ });
128
+ },
129
+ intervalMinutes * 60 * 1000,
130
+ );
131
+ }
132
+
133
+ async stopProactiveMode(): Promise<void> {
134
+ if (this.proactiveTimer) {
135
+ clearInterval(this.proactiveTimer);
136
+ this.proactiveTimer = undefined;
137
+ }
138
+ }
139
+
140
+ private async gatherContext(): Promise<string> {
141
+ const contextLines: string[] = [];
142
+
143
+ // System Info
144
+ try {
145
+ const sysPlugin = await this.plugins.getPlugin('system');
146
+ if (sysPlugin) {
147
+ const infoTool = sysPlugin.getTools().find((t) => t.name === 'system_info');
148
+ if (infoTool) {
149
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
150
+ const stats = (await infoTool.handler({})) as any;
151
+ contextLines.push(
152
+ `[SYSTEM] CPU: ${stats.cpu?.load || 'unknown'}%, RAM: ${stats.memory?.usedPercent || 'unknown'}%, Disk: ${stats.disk?.usedPercent || 'unknown'}%`,
153
+ );
154
+ }
155
+ }
156
+ } catch {
157
+ /* plugin might be disabled */
158
+ }
159
+
160
+ // Recent Activity
161
+ const activity = await this.getRecentActivity(5);
162
+ if (activity.length > 0) {
163
+ contextLines.push('[RECENT ACTIVITY]');
164
+ activity.forEach((a) => contextLines.push(`- ${a.timestamp}: ${a.event_type} (${a.service})`));
165
+ }
166
+
167
+ // enabled plugins
168
+ const enabled = this.config.get<string[]>('plugins.enabled') || [];
169
+ contextLines.push(`[PLUGINS] Enabled: ${enabled.join(', ')}`);
170
+
171
+ // Dynamic context from any enabled plugin that implements getContext()
172
+ for (const pluginName of enabled) {
173
+ try {
174
+ const plugin = await this.plugins.getPlugin(pluginName);
175
+ if (plugin && typeof plugin.getContext === 'function') {
176
+ const ctx = await plugin.getContext();
177
+ if (ctx) contextLines.push(ctx);
178
+ }
179
+ } catch {
180
+ /* ignore — plugin context is best-effort */
181
+ }
182
+ }
183
+
184
+ return contextLines.join('\n');
185
+ }
186
+
187
+ public async runReasoningCycle(): Promise<void> {
188
+ if (!this.initialized) return;
189
+
190
+ if (this._cycleRunning) {
191
+ process.stderr.write('[Proactive] Skipping cycle — previous cycle still running\n');
192
+ return;
193
+ }
194
+
195
+ this._cycleRunning = true;
196
+ await this.db.logActivity('system', 'proactive_cycle_start');
197
+
198
+ try {
199
+ const context = await this.gatherContext();
200
+ const provider = await this.ai.getCurrentProvider();
201
+
202
+ if (provider) {
203
+ const prompt = `You are running your autonomous periodic reasoning cycle.
204
+ Examine the context below. If there is a problem (like high CPU, or important unread emails), use your tools to take action or investigate further.
205
+ If everything is perfectly normal and no action is required, respond exactly with "No action needed."
206
+
207
+ CONTEXT:
208
+ ${context}`;
209
+
210
+ const systemUserId = 'system-proactive';
211
+ const agentResponse = await this.ai.handleConversation(systemUserId, prompt);
212
+
213
+ await this.db.logActivity('system', 'proactive_reasoning_complete', agentResponse.text);
214
+
215
+ if (!this.quiet) {
216
+ process.stderr.write(` 🤖 [Proactive] ${agentResponse.text}\n`);
217
+ }
218
+
219
+ if (agentResponse.approvalRequired) {
220
+ const { toolName, arguments: args } = agentResponse.approvalRequired;
221
+ await this.notifyUser({
222
+ title: 'Approval Required',
223
+ body: `The AI attempted to use "${toolName}" autonomously. Reply to approve or deny.`,
224
+ codeBlock: JSON.stringify(args, null, 2),
225
+ });
226
+ } else if (agentResponse.text && !agentResponse.text.toLowerCase().includes('no action needed')) {
227
+ await this.notifyUser({
228
+ title: 'Autonomous Action',
229
+ body: agentResponse.text,
230
+ });
231
+ }
232
+ }
233
+ } catch (err: any) {
234
+ process.stderr.write(` ✗ [Proactive Error] ${err.message}\n`);
235
+ } finally {
236
+ this._cycleRunning = false;
237
+ await this.db.logActivity('system', 'proactive_cycle_end');
238
+ }
239
+ }
240
+ }