patchwork-os 0.2.0-beta.1 → 0.2.0-beta.10.canary.95

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 (652) hide show
  1. package/README.bridge.md +14 -14
  2. package/README.md +201 -34
  3. package/deploy/README.md +1 -1
  4. package/deploy/bootstrap-vps.sh +14 -9
  5. package/deploy/deploy-dashboard.sh +25 -1
  6. package/deploy/macos/README.md +153 -0
  7. package/deploy/macos/com.patchwork.bridge.plist.template +54 -0
  8. package/deploy/macos/com.patchwork.tunnel.plist.template +76 -0
  9. package/deploy/macos/install-mac-bridge.sh +244 -0
  10. package/deploy/macos/uninstall-mac-bridge.sh +22 -0
  11. package/dist/activityLog.d.ts +6 -0
  12. package/dist/activityLog.js +63 -26
  13. package/dist/activityLog.js.map +1 -1
  14. package/dist/adapters/claude.js +22 -16
  15. package/dist/adapters/claude.js.map +1 -1
  16. package/dist/adapters/gemini.js +15 -11
  17. package/dist/adapters/gemini.js.map +1 -1
  18. package/dist/adapters/openai.js +9 -9
  19. package/dist/adapters/openai.js.map +1 -1
  20. package/dist/ajv2020.d.ts +25 -0
  21. package/dist/ajv2020.js +33 -0
  22. package/dist/ajv2020.js.map +1 -0
  23. package/dist/analyticsAggregator.js +1 -1
  24. package/dist/analyticsAggregator.js.map +1 -1
  25. package/dist/analyticsConfig.d.ts +29 -0
  26. package/dist/analyticsConfig.js +102 -0
  27. package/dist/analyticsConfig.js.map +1 -0
  28. package/dist/analyticsPrefs.d.ts +38 -2
  29. package/dist/analyticsPrefs.js +148 -23
  30. package/dist/analyticsPrefs.js.map +1 -1
  31. package/dist/analyticsSend.d.ts +17 -1
  32. package/dist/analyticsSend.js +67 -5
  33. package/dist/analyticsSend.js.map +1 -1
  34. package/dist/approvalHttp.d.ts +14 -0
  35. package/dist/approvalHttp.js +212 -9
  36. package/dist/approvalHttp.js.map +1 -1
  37. package/dist/approvalInsights.js +13 -5
  38. package/dist/approvalInsights.js.map +1 -1
  39. package/dist/approvalQueue.d.ts +97 -3
  40. package/dist/approvalQueue.js +193 -19
  41. package/dist/approvalQueue.js.map +1 -1
  42. package/dist/approvalSignals.js +19 -11
  43. package/dist/approvalSignals.js.map +1 -1
  44. package/dist/automation.d.ts +35 -10
  45. package/dist/automation.js +133 -37
  46. package/dist/automation.js.map +1 -1
  47. package/dist/automationSuggestions.js +10 -8
  48. package/dist/automationSuggestions.js.map +1 -1
  49. package/dist/bridge.d.ts +2 -0
  50. package/dist/bridge.js +202 -25
  51. package/dist/bridge.js.map +1 -1
  52. package/dist/bridgeLockDiscovery.d.ts +27 -1
  53. package/dist/bridgeLockDiscovery.js +38 -11
  54. package/dist/bridgeLockDiscovery.js.map +1 -1
  55. package/dist/bridgeToken.js +3 -2
  56. package/dist/bridgeToken.js.map +1 -1
  57. package/dist/claudeDriver.js +23 -8
  58. package/dist/claudeDriver.js.map +1 -1
  59. package/dist/claudeOrchestrator.d.ts +1 -1
  60. package/dist/claudeOrchestrator.js +87 -44
  61. package/dist/claudeOrchestrator.js.map +1 -1
  62. package/dist/commands/analytics.d.ts +8 -0
  63. package/dist/commands/analytics.js +134 -0
  64. package/dist/commands/analytics.js.map +1 -0
  65. package/dist/commands/auditEnv.d.ts +36 -0
  66. package/dist/commands/auditEnv.js +202 -0
  67. package/dist/commands/auditEnv.js.map +1 -0
  68. package/dist/commands/dashboard.js +8 -1
  69. package/dist/commands/dashboard.js.map +1 -1
  70. package/dist/commands/doctor.d.ts +35 -0
  71. package/dist/commands/doctor.js +51 -0
  72. package/dist/commands/doctor.js.map +1 -0
  73. package/dist/commands/install.js +3 -0
  74. package/dist/commands/install.js.map +1 -1
  75. package/dist/commands/launchd.js +15 -16
  76. package/dist/commands/launchd.js.map +1 -1
  77. package/dist/commands/patchworkInit.d.ts +5 -0
  78. package/dist/commands/patchworkInit.js +89 -7
  79. package/dist/commands/patchworkInit.js.map +1 -1
  80. package/dist/commands/recipe.d.ts +110 -0
  81. package/dist/commands/recipe.js +512 -9
  82. package/dist/commands/recipe.js.map +1 -1
  83. package/dist/commands/recipeInstall.js +11 -4
  84. package/dist/commands/recipeInstall.js.map +1 -1
  85. package/dist/commands/shadowScan.d.ts +34 -0
  86. package/dist/commands/shadowScan.js +142 -0
  87. package/dist/commands/shadowScan.js.map +1 -0
  88. package/dist/commands/task.js +2 -2
  89. package/dist/commands/task.js.map +1 -1
  90. package/dist/commands/tools.d.ts +20 -1
  91. package/dist/commands/tools.js +112 -3
  92. package/dist/commands/tools.js.map +1 -1
  93. package/dist/commands/tracesImport.js +21 -4
  94. package/dist/commands/tracesImport.js.map +1 -1
  95. package/dist/commitIssueLinkLog.d.ts +16 -0
  96. package/dist/commitIssueLinkLog.js +110 -24
  97. package/dist/commitIssueLinkLog.js.map +1 -1
  98. package/dist/companions/registry.js +15 -7
  99. package/dist/companions/registry.js.map +1 -1
  100. package/dist/config.d.ts +47 -3
  101. package/dist/config.js +111 -21
  102. package/dist/config.js.map +1 -1
  103. package/dist/connectorRoutes.js +866 -57
  104. package/dist/connectorRoutes.js.map +1 -1
  105. package/dist/connectors/airtable.d.ts +230 -0
  106. package/dist/connectors/airtable.js +700 -0
  107. package/dist/connectors/airtable.js.map +1 -0
  108. package/dist/connectors/asana.js +13 -9
  109. package/dist/connectors/asana.js.map +1 -1
  110. package/dist/connectors/baseConnector.js +25 -3
  111. package/dist/connectors/baseConnector.js.map +1 -1
  112. package/dist/connectors/caldiy.d.ts +137 -0
  113. package/dist/connectors/caldiy.js +424 -0
  114. package/dist/connectors/caldiy.js.map +1 -0
  115. package/dist/connectors/circleci.d.ts +162 -0
  116. package/dist/connectors/circleci.js +576 -0
  117. package/dist/connectors/circleci.js.map +1 -0
  118. package/dist/connectors/cloudflare.d.ts +132 -0
  119. package/dist/connectors/cloudflare.js +622 -0
  120. package/dist/connectors/cloudflare.js.map +1 -0
  121. package/dist/connectors/confluence.js +35 -0
  122. package/dist/connectors/confluence.js.map +1 -1
  123. package/dist/connectors/connectorRedirectUri.d.ts +30 -0
  124. package/dist/connectors/connectorRedirectUri.js +38 -0
  125. package/dist/connectors/connectorRedirectUri.js.map +1 -0
  126. package/dist/connectors/connectorRegistry.d.ts +63 -0
  127. package/dist/connectors/connectorRegistry.js +354 -0
  128. package/dist/connectors/connectorRegistry.js.map +1 -0
  129. package/dist/connectors/datadog.js +33 -4
  130. package/dist/connectors/datadog.js.map +1 -1
  131. package/dist/connectors/discord.js +14 -10
  132. package/dist/connectors/discord.js.map +1 -1
  133. package/dist/connectors/elasticsearch.d.ts +141 -0
  134. package/dist/connectors/elasticsearch.js +601 -0
  135. package/dist/connectors/elasticsearch.js.map +1 -0
  136. package/dist/connectors/figma.d.ts +130 -0
  137. package/dist/connectors/figma.js +387 -0
  138. package/dist/connectors/figma.js.map +1 -0
  139. package/dist/connectors/github.d.ts +17 -0
  140. package/dist/connectors/github.js +53 -2
  141. package/dist/connectors/github.js.map +1 -1
  142. package/dist/connectors/gitlab.js +12 -6
  143. package/dist/connectors/gitlab.js.map +1 -1
  144. package/dist/connectors/gmail.js +72 -21
  145. package/dist/connectors/gmail.js.map +1 -1
  146. package/dist/connectors/googleCalendar.js +8 -8
  147. package/dist/connectors/googleCalendar.js.map +1 -1
  148. package/dist/connectors/googleDocs.d.ts +103 -0
  149. package/dist/connectors/googleDocs.js +409 -0
  150. package/dist/connectors/googleDocs.js.map +1 -0
  151. package/dist/connectors/googleDrive.d.ts +12 -0
  152. package/dist/connectors/googleDrive.js +35 -8
  153. package/dist/connectors/googleDrive.js.map +1 -1
  154. package/dist/connectors/grafana.d.ts +133 -0
  155. package/dist/connectors/grafana.js +478 -0
  156. package/dist/connectors/grafana.js.map +1 -0
  157. package/dist/connectors/jira.d.ts +25 -0
  158. package/dist/connectors/jira.js +227 -1
  159. package/dist/connectors/jira.js.map +1 -1
  160. package/dist/connectors/linear.js +1 -1
  161. package/dist/connectors/linear.js.map +1 -1
  162. package/dist/connectors/mcpOAuth.js +78 -16
  163. package/dist/connectors/mcpOAuth.js.map +1 -1
  164. package/dist/connectors/monday.d.ts +217 -0
  165. package/dist/connectors/monday.js +655 -0
  166. package/dist/connectors/monday.js.map +1 -0
  167. package/dist/connectors/mongodb.d.ts +139 -0
  168. package/dist/connectors/mongodb.js +455 -0
  169. package/dist/connectors/mongodb.js.map +1 -0
  170. package/dist/connectors/oauthStateStore.d.ts +20 -0
  171. package/dist/connectors/oauthStateStore.js +94 -4
  172. package/dist/connectors/oauthStateStore.js.map +1 -1
  173. package/dist/connectors/obsidian.d.ts +83 -0
  174. package/dist/connectors/obsidian.js +441 -0
  175. package/dist/connectors/obsidian.js.map +1 -0
  176. package/dist/connectors/paystack.d.ts +159 -0
  177. package/dist/connectors/paystack.js +607 -0
  178. package/dist/connectors/paystack.js.map +1 -0
  179. package/dist/connectors/pipedrive.d.ts +189 -0
  180. package/dist/connectors/pipedrive.js +559 -0
  181. package/dist/connectors/pipedrive.js.map +1 -0
  182. package/dist/connectors/postgres.d.ts +127 -0
  183. package/dist/connectors/postgres.js +512 -0
  184. package/dist/connectors/postgres.js.map +1 -0
  185. package/dist/connectors/posthog.d.ts +119 -0
  186. package/dist/connectors/posthog.js +479 -0
  187. package/dist/connectors/posthog.js.map +1 -0
  188. package/dist/connectors/redis.d.ts +140 -0
  189. package/dist/connectors/redis.js +571 -0
  190. package/dist/connectors/redis.js.map +1 -0
  191. package/dist/connectors/resend.d.ts +131 -0
  192. package/dist/connectors/resend.js +529 -0
  193. package/dist/connectors/resend.js.map +1 -0
  194. package/dist/connectors/salesforce.d.ts +136 -0
  195. package/dist/connectors/salesforce.js +603 -0
  196. package/dist/connectors/salesforce.js.map +1 -0
  197. package/dist/connectors/secrets.d.ts +51 -0
  198. package/dist/connectors/secrets.js +102 -0
  199. package/dist/connectors/secrets.js.map +1 -0
  200. package/dist/connectors/sendgrid.d.ts +102 -0
  201. package/dist/connectors/sendgrid.js +423 -0
  202. package/dist/connectors/sendgrid.js.map +1 -0
  203. package/dist/connectors/shopify.d.ts +145 -0
  204. package/dist/connectors/shopify.js +502 -0
  205. package/dist/connectors/shopify.js.map +1 -0
  206. package/dist/connectors/slack.d.ts +1 -1
  207. package/dist/connectors/slack.js +61 -9
  208. package/dist/connectors/slack.js.map +1 -1
  209. package/dist/connectors/snowflake.d.ts +119 -0
  210. package/dist/connectors/snowflake.js +615 -0
  211. package/dist/connectors/snowflake.js.map +1 -0
  212. package/dist/connectors/supabase.d.ts +92 -0
  213. package/dist/connectors/supabase.js +630 -0
  214. package/dist/connectors/supabase.js.map +1 -0
  215. package/dist/connectors/todoist.d.ts +117 -0
  216. package/dist/connectors/todoist.js +485 -0
  217. package/dist/connectors/todoist.js.map +1 -0
  218. package/dist/connectors/tokenStorage.js +56 -14
  219. package/dist/connectors/tokenStorage.js.map +1 -1
  220. package/dist/connectors/twilio.d.ts +118 -0
  221. package/dist/connectors/twilio.js +475 -0
  222. package/dist/connectors/twilio.js.map +1 -0
  223. package/dist/connectors/vercel.d.ts +110 -0
  224. package/dist/connectors/vercel.js +479 -0
  225. package/dist/connectors/vercel.js.map +1 -0
  226. package/dist/connectors/webflow.d.ts +118 -0
  227. package/dist/connectors/webflow.js +393 -0
  228. package/dist/connectors/webflow.js.map +1 -0
  229. package/dist/connectors/woocommerce.d.ts +220 -0
  230. package/dist/connectors/woocommerce.js +464 -0
  231. package/dist/connectors/woocommerce.js.map +1 -0
  232. package/dist/crypto.js +7 -2
  233. package/dist/crypto.js.map +1 -1
  234. package/dist/decisionReplay.js +15 -6
  235. package/dist/decisionReplay.js.map +1 -1
  236. package/dist/decisionTraceLog.d.ts +28 -0
  237. package/dist/decisionTraceLog.js +156 -29
  238. package/dist/decisionTraceLog.js.map +1 -1
  239. package/dist/drivers/claude/api.js +5 -4
  240. package/dist/drivers/claude/api.js.map +1 -1
  241. package/dist/drivers/claude/envSanitizer.d.ts +0 -6
  242. package/dist/drivers/claude/envSanitizer.js +17 -2
  243. package/dist/drivers/claude/envSanitizer.js.map +1 -1
  244. package/dist/drivers/claude/streamParser.js +5 -4
  245. package/dist/drivers/claude/streamParser.js.map +1 -1
  246. package/dist/drivers/claude/subprocess.js +22 -3
  247. package/dist/drivers/claude/subprocess.js.map +1 -1
  248. package/dist/drivers/gemini/index.d.ts +22 -0
  249. package/dist/drivers/gemini/index.js +256 -129
  250. package/dist/drivers/gemini/index.js.map +1 -1
  251. package/dist/drivers/local/index.d.ts +17 -0
  252. package/dist/drivers/local/index.js +99 -0
  253. package/dist/drivers/local/index.js.map +1 -1
  254. package/dist/drivers/openai/index.js +30 -2
  255. package/dist/drivers/openai/index.js.map +1 -1
  256. package/dist/extensionClient.d.ts +37 -4
  257. package/dist/extensionClient.js +58 -16
  258. package/dist/extensionClient.js.map +1 -1
  259. package/dist/featureFlags.d.ts +91 -0
  260. package/dist/featureFlags.js +174 -3
  261. package/dist/featureFlags.js.map +1 -1
  262. package/dist/fileLock.js +21 -12
  263. package/dist/fileLock.js.map +1 -1
  264. package/dist/fileLockSync.d.ts +67 -0
  265. package/dist/fileLockSync.js +126 -0
  266. package/dist/fileLockSync.js.map +1 -0
  267. package/dist/fp/activityAnalytics.js +26 -12
  268. package/dist/fp/activityAnalytics.js.map +1 -1
  269. package/dist/fp/automationInterpreter.d.ts +15 -1
  270. package/dist/fp/automationInterpreter.js +217 -82
  271. package/dist/fp/automationInterpreter.js.map +1 -1
  272. package/dist/fp/automationProgram.d.ts +30 -0
  273. package/dist/fp/automationProgram.js.map +1 -1
  274. package/dist/fp/automationState.d.ts +24 -5
  275. package/dist/fp/automationState.js +56 -9
  276. package/dist/fp/automationState.js.map +1 -1
  277. package/dist/fp/automationUtils.js +1 -1
  278. package/dist/fp/automationUtils.js.map +1 -1
  279. package/dist/fp/commandDescription.js +7 -1
  280. package/dist/fp/commandDescription.js.map +1 -1
  281. package/dist/fp/extensionSnapshot.js +8 -2
  282. package/dist/fp/extensionSnapshot.js.map +1 -1
  283. package/dist/fp/interpreterContext.d.ts +66 -1
  284. package/dist/fp/interpreterContext.js +91 -1
  285. package/dist/fp/interpreterContext.js.map +1 -1
  286. package/dist/fp/policyParser.js +29 -1
  287. package/dist/fp/policyParser.js.map +1 -1
  288. package/dist/fsWatchWithFallback.d.ts +36 -0
  289. package/dist/fsWatchWithFallback.js +128 -0
  290. package/dist/fsWatchWithFallback.js.map +1 -0
  291. package/dist/haltPushDispatch.d.ts +33 -0
  292. package/dist/haltPushDispatch.js +103 -0
  293. package/dist/haltPushDispatch.js.map +1 -0
  294. package/dist/httpBodyValidation.d.ts +41 -0
  295. package/dist/httpBodyValidation.js +45 -0
  296. package/dist/httpBodyValidation.js.map +1 -0
  297. package/dist/inboxRoutes.d.ts +22 -0
  298. package/dist/inboxRoutes.js +61 -1
  299. package/dist/inboxRoutes.js.map +1 -1
  300. package/dist/index.js +1053 -76
  301. package/dist/index.js.map +1 -1
  302. package/dist/installGuard.js +6 -2
  303. package/dist/installGuard.js.map +1 -1
  304. package/dist/lockfile.js +31 -4
  305. package/dist/lockfile.js.map +1 -1
  306. package/dist/oauth.d.ts +9 -0
  307. package/dist/oauth.js +33 -0
  308. package/dist/oauth.js.map +1 -1
  309. package/dist/oauthRoutes.d.ts +1 -1
  310. package/dist/oauthRoutes.js +5 -3
  311. package/dist/oauthRoutes.js.map +1 -1
  312. package/dist/orchestrator/childBridgeRegistry.js +29 -11
  313. package/dist/orchestrator/childBridgeRegistry.js.map +1 -1
  314. package/dist/patchworkConfig.d.ts +44 -1
  315. package/dist/patchworkConfig.js +28 -3
  316. package/dist/patchworkConfig.js.map +1 -1
  317. package/dist/pluginLoader.js +10 -1
  318. package/dist/pluginLoader.js.map +1 -1
  319. package/dist/pluginWatcher.js +12 -14
  320. package/dist/pluginWatcher.js.map +1 -1
  321. package/dist/preToolUseHook.js +3 -2
  322. package/dist/preToolUseHook.js.map +1 -1
  323. package/dist/processTree.d.ts +34 -0
  324. package/dist/processTree.js +105 -0
  325. package/dist/processTree.js.map +1 -0
  326. package/dist/prompts.js +3 -3
  327. package/dist/prompts.js.map +1 -1
  328. package/dist/recipeOrchestration.d.ts +9 -0
  329. package/dist/recipeOrchestration.js +341 -24
  330. package/dist/recipeOrchestration.js.map +1 -1
  331. package/dist/recipeRoutes.d.ts +58 -2
  332. package/dist/recipeRoutes.js +744 -115
  333. package/dist/recipeRoutes.js.map +1 -1
  334. package/dist/recipes/RecipeOrchestrator.d.ts +2 -0
  335. package/dist/recipes/RecipeOrchestrator.js +6 -1
  336. package/dist/recipes/RecipeOrchestrator.js.map +1 -1
  337. package/dist/recipes/agentExecutor.d.ts +25 -5
  338. package/dist/recipes/agentExecutor.js.map +1 -1
  339. package/dist/recipes/chainedRunner.d.ts +2 -0
  340. package/dist/recipes/chainedRunner.js +142 -5
  341. package/dist/recipes/chainedRunner.js.map +1 -1
  342. package/dist/recipes/connectorPreflight.d.ts +66 -0
  343. package/dist/recipes/connectorPreflight.js +169 -0
  344. package/dist/recipes/connectorPreflight.js.map +1 -0
  345. package/dist/recipes/dependencyGraph.js +13 -5
  346. package/dist/recipes/dependencyGraph.js.map +1 -1
  347. package/dist/recipes/githubInstallSource.d.ts +128 -0
  348. package/dist/recipes/githubInstallSource.js +206 -0
  349. package/dist/recipes/githubInstallSource.js.map +1 -0
  350. package/dist/recipes/haltCategory.d.ts +119 -0
  351. package/dist/recipes/haltCategory.js +188 -0
  352. package/dist/recipes/haltCategory.js.map +1 -0
  353. package/dist/recipes/idempotencyKey.d.ts +134 -0
  354. package/dist/recipes/idempotencyKey.js +322 -0
  355. package/dist/recipes/idempotencyKey.js.map +1 -0
  356. package/dist/recipes/installer.js +48 -2
  357. package/dist/recipes/installer.js.map +1 -1
  358. package/dist/recipes/judgeSummary.d.ts +50 -0
  359. package/dist/recipes/judgeSummary.js +47 -0
  360. package/dist/recipes/judgeSummary.js.map +1 -0
  361. package/dist/recipes/judgeVerdict.d.ts +48 -0
  362. package/dist/recipes/judgeVerdict.js +174 -0
  363. package/dist/recipes/judgeVerdict.js.map +1 -0
  364. package/dist/recipes/migrations/index.d.ts +9 -0
  365. package/dist/recipes/migrations/index.js +133 -0
  366. package/dist/recipes/migrations/index.js.map +1 -1
  367. package/dist/recipes/names.d.ts +20 -0
  368. package/dist/recipes/names.js +25 -0
  369. package/dist/recipes/names.js.map +1 -1
  370. package/dist/recipes/parser.js +88 -5
  371. package/dist/recipes/parser.js.map +1 -1
  372. package/dist/recipes/replayRun.js +1 -1
  373. package/dist/recipes/replayRun.js.map +1 -1
  374. package/dist/recipes/runBudget.d.ts +70 -0
  375. package/dist/recipes/runBudget.js +109 -0
  376. package/dist/recipes/runBudget.js.map +1 -0
  377. package/dist/recipes/scheduler.d.ts +30 -0
  378. package/dist/recipes/scheduler.js +69 -19
  379. package/dist/recipes/scheduler.js.map +1 -1
  380. package/dist/recipes/schema.d.ts +36 -0
  381. package/dist/recipes/schemaGenerator.js +103 -5
  382. package/dist/recipes/schemaGenerator.js.map +1 -1
  383. package/dist/recipes/stepObservation.js +9 -0
  384. package/dist/recipes/stepObservation.js.map +1 -1
  385. package/dist/recipes/toolRegistry.js +20 -3
  386. package/dist/recipes/toolRegistry.js.map +1 -1
  387. package/dist/recipes/tools/fanOut.d.ts +20 -0
  388. package/dist/recipes/tools/fanOut.js +199 -0
  389. package/dist/recipes/tools/fanOut.js.map +1 -0
  390. package/dist/recipes/tools/file.js +5 -2
  391. package/dist/recipes/tools/file.js.map +1 -1
  392. package/dist/recipes/tools/github.d.ts +1 -1
  393. package/dist/recipes/tools/github.js +75 -1
  394. package/dist/recipes/tools/github.js.map +1 -1
  395. package/dist/recipes/tools/gmail.js +27 -5
  396. package/dist/recipes/tools/gmail.js.map +1 -1
  397. package/dist/recipes/tools/googleDrive.js +64 -0
  398. package/dist/recipes/tools/googleDrive.js.map +1 -1
  399. package/dist/recipes/tools/http.d.ts +10 -0
  400. package/dist/recipes/tools/http.js +176 -0
  401. package/dist/recipes/tools/http.js.map +1 -0
  402. package/dist/recipes/tools/index.d.ts +2 -0
  403. package/dist/recipes/tools/index.js +2 -0
  404. package/dist/recipes/tools/index.js.map +1 -1
  405. package/dist/recipes/tools/slack.js +1 -1
  406. package/dist/recipes/validation.d.ts +17 -0
  407. package/dist/recipes/validation.js +29 -11
  408. package/dist/recipes/validation.js.map +1 -1
  409. package/dist/recipes/workspaceRoot.d.ts +37 -0
  410. package/dist/recipes/workspaceRoot.js +73 -0
  411. package/dist/recipes/workspaceRoot.js.map +1 -0
  412. package/dist/recipes/yamlPositions.d.ts +56 -0
  413. package/dist/recipes/yamlPositions.js +183 -0
  414. package/dist/recipes/yamlPositions.js.map +1 -0
  415. package/dist/recipes/yamlRunner.d.ts +182 -8
  416. package/dist/recipes/yamlRunner.js +877 -217
  417. package/dist/recipes/yamlRunner.js.map +1 -1
  418. package/dist/recipesHttp.d.ts +19 -3
  419. package/dist/recipesHttp.js +67 -11
  420. package/dist/recipesHttp.js.map +1 -1
  421. package/dist/resources.js +21 -13
  422. package/dist/resources.js.map +1 -1
  423. package/dist/runLog.d.ts +58 -5
  424. package/dist/runLog.js +98 -21
  425. package/dist/runLog.js.map +1 -1
  426. package/dist/sanitizeParsedJson.d.ts +39 -0
  427. package/dist/sanitizeParsedJson.js +55 -0
  428. package/dist/sanitizeParsedJson.js.map +1 -0
  429. package/dist/schemas/recipe.v1.json +885 -196
  430. package/dist/server.d.ts +160 -3
  431. package/dist/server.js +1099 -122
  432. package/dist/server.js.map +1 -1
  433. package/dist/sessionCheckpoint.d.ts +8 -0
  434. package/dist/sessionCheckpoint.js +33 -3
  435. package/dist/sessionCheckpoint.js.map +1 -1
  436. package/dist/ssrfGuard.d.ts +16 -0
  437. package/dist/ssrfGuard.js +87 -4
  438. package/dist/ssrfGuard.js.map +1 -1
  439. package/dist/streamableHttp.d.ts +9 -4
  440. package/dist/streamableHttp.js +76 -20
  441. package/dist/streamableHttp.js.map +1 -1
  442. package/dist/telemetry.js +19 -12
  443. package/dist/telemetry.js.map +1 -1
  444. package/dist/testing/shadowRun.d.ts +52 -0
  445. package/dist/testing/shadowRun.js +71 -0
  446. package/dist/testing/shadowRun.js.map +1 -0
  447. package/dist/tools/batchLsp.d.ts +3 -0
  448. package/dist/tools/bridgeDoctor.d.ts +11 -0
  449. package/dist/tools/bridgeDoctor.js +48 -2
  450. package/dist/tools/bridgeDoctor.js.map +1 -1
  451. package/dist/tools/bridgeStatus.d.ts +0 -12
  452. package/dist/tools/bridgeStatus.js +2 -28
  453. package/dist/tools/bridgeStatus.js.map +1 -1
  454. package/dist/tools/cancelClaudeTask.d.ts +1 -0
  455. package/dist/tools/clipboard.d.ts +2 -0
  456. package/dist/tools/closeTabs.d.ts +1 -0
  457. package/dist/tools/codeLens.d.ts +1 -0
  458. package/dist/tools/createIssueFromAIComment.d.ts +1 -0
  459. package/dist/tools/ctxGetTaskContext.d.ts +9 -0
  460. package/dist/tools/ctxGetTaskContext.js +50 -2
  461. package/dist/tools/ctxGetTaskContext.js.map +1 -1
  462. package/dist/tools/ctxQueryTraces.js +32 -24
  463. package/dist/tools/ctxQueryTraces.js.map +1 -1
  464. package/dist/tools/ctxSaveTrace.d.ts +1 -0
  465. package/dist/tools/debug.d.ts +4 -0
  466. package/dist/tools/decorations.d.ts +2 -0
  467. package/dist/tools/detectUnusedCode.js +9 -7
  468. package/dist/tools/detectUnusedCode.js.map +1 -1
  469. package/dist/tools/documentLinks.d.ts +1 -0
  470. package/dist/tools/editText.d.ts +1 -0
  471. package/dist/tools/editText.js +2 -1
  472. package/dist/tools/editText.js.map +1 -1
  473. package/dist/tools/enrichCommit.d.ts +1 -0
  474. package/dist/tools/enrichStackTrace.js +11 -5
  475. package/dist/tools/enrichStackTrace.js.map +1 -1
  476. package/dist/tools/explainDiagnostic.d.ts +1 -0
  477. package/dist/tools/explainSymbol.d.ts +1 -0
  478. package/dist/tools/fileOperations.d.ts +3 -0
  479. package/dist/tools/fileOperations.js +2 -1
  480. package/dist/tools/fileOperations.js.map +1 -1
  481. package/dist/tools/fileWatcher.d.ts +2 -0
  482. package/dist/tools/fileWatcher.js +8 -2
  483. package/dist/tools/fileWatcher.js.map +1 -1
  484. package/dist/tools/findFiles.d.ts +1 -0
  485. package/dist/tools/fixAllLintErrors.d.ts +1 -0
  486. package/dist/tools/fixAllLintErrors.js +10 -5
  487. package/dist/tools/fixAllLintErrors.js.map +1 -1
  488. package/dist/tools/foldingRanges.d.ts +1 -0
  489. package/dist/tools/formatDocument.d.ts +1 -0
  490. package/dist/tools/formatDocument.js +10 -5
  491. package/dist/tools/formatDocument.js.map +1 -1
  492. package/dist/tools/generateTests.d.ts +1 -0
  493. package/dist/tools/getAIComments.d.ts +1 -0
  494. package/dist/tools/getAnalyticsReport.js +5 -1
  495. package/dist/tools/getAnalyticsReport.js.map +1 -1
  496. package/dist/tools/getBufferContent.d.ts +1 -0
  497. package/dist/tools/getChangeImpact.d.ts +1 -0
  498. package/dist/tools/getChangeImpact.js +23 -14
  499. package/dist/tools/getChangeImpact.js.map +1 -1
  500. package/dist/tools/getClaudeTaskStatus.d.ts +1 -0
  501. package/dist/tools/getCodeCoverage.d.ts +1 -0
  502. package/dist/tools/getCodeCoverage.js +32 -14
  503. package/dist/tools/getCodeCoverage.js.map +1 -1
  504. package/dist/tools/getCommitsForIssue.d.ts +1 -0
  505. package/dist/tools/getDebugState.d.ts +1 -0
  506. package/dist/tools/getDiagnostics.js +32 -29
  507. package/dist/tools/getDiagnostics.js.map +1 -1
  508. package/dist/tools/getDiffFromHandoff.js +8 -2
  509. package/dist/tools/getDiffFromHandoff.js.map +1 -1
  510. package/dist/tools/getDocumentSymbols.d.ts +1 -0
  511. package/dist/tools/getGitHotspots.d.ts +1 -0
  512. package/dist/tools/getImportedSignatures.d.ts +1 -0
  513. package/dist/tools/getImportedSignatures.js +18 -14
  514. package/dist/tools/getImportedSignatures.js.map +1 -1
  515. package/dist/tools/getPRTemplate.d.ts +1 -0
  516. package/dist/tools/getProjectContext.js +23 -10
  517. package/dist/tools/getProjectContext.js.map +1 -1
  518. package/dist/tools/getSymbolHistory.d.ts +1 -0
  519. package/dist/tools/getToolCapabilities.d.ts +10 -5
  520. package/dist/tools/getToolCapabilities.js +79 -202
  521. package/dist/tools/getToolCapabilities.js.map +1 -1
  522. package/dist/tools/getTypeSignature.d.ts +1 -0
  523. package/dist/tools/getWorkspaceSettings.d.ts +1 -0
  524. package/dist/tools/gitWrite.d.ts +11 -0
  525. package/dist/tools/github/actions.d.ts +2 -0
  526. package/dist/tools/github/composite.d.ts +3 -0
  527. package/dist/tools/github/issues.d.ts +4 -0
  528. package/dist/tools/github/pr.d.ts +7 -0
  529. package/dist/tools/handoffNote.d.ts +1 -0
  530. package/dist/tools/handoffNote.js +2 -1
  531. package/dist/tools/handoffNote.js.map +1 -1
  532. package/dist/tools/headless/lspClient.js +3 -0
  533. package/dist/tools/headless/lspClient.js.map +1 -1
  534. package/dist/tools/hoverAtCursor.d.ts +1 -0
  535. package/dist/tools/httpClient.d.ts +2 -0
  536. package/dist/tools/httpClient.js +38 -71
  537. package/dist/tools/httpClient.js.map +1 -1
  538. package/dist/tools/inlayHints.d.ts +1 -0
  539. package/dist/tools/launchQuickTask.d.ts +1 -0
  540. package/dist/tools/listClaudeTasks.d.ts +1 -0
  541. package/dist/tools/listClaudeTasks.js +10 -8
  542. package/dist/tools/listClaudeTasks.js.map +1 -1
  543. package/dist/tools/listTerminals.d.ts +1 -0
  544. package/dist/tools/lsp.d.ts +15 -0
  545. package/dist/tools/lsp.js +17 -0
  546. package/dist/tools/lsp.js.map +1 -1
  547. package/dist/tools/navigateToSymbolByName.d.ts +1 -0
  548. package/dist/tools/openDiff.d.ts +1 -0
  549. package/dist/tools/openDiff.js +4 -1
  550. package/dist/tools/openDiff.js.map +1 -1
  551. package/dist/tools/openFile.d.ts +1 -0
  552. package/dist/tools/openFile.js +4 -1
  553. package/dist/tools/openFile.js.map +1 -1
  554. package/dist/tools/openInBrowser.js +6 -1
  555. package/dist/tools/openInBrowser.js.map +1 -1
  556. package/dist/tools/organizeImports.d.ts +1 -0
  557. package/dist/tools/organizeImports.js +5 -3
  558. package/dist/tools/organizeImports.js.map +1 -1
  559. package/dist/tools/performanceReport.js +5 -3
  560. package/dist/tools/performanceReport.js.map +1 -1
  561. package/dist/tools/planPersistence.d.ts +3 -0
  562. package/dist/tools/planPersistence.js +4 -1
  563. package/dist/tools/planPersistence.js.map +1 -1
  564. package/dist/tools/previewEdit.d.ts +1 -0
  565. package/dist/tools/previewEdit.js +15 -4
  566. package/dist/tools/previewEdit.js.map +1 -1
  567. package/dist/tools/recentTracesDigest.js +54 -11
  568. package/dist/tools/recentTracesDigest.js.map +1 -1
  569. package/dist/tools/refactorAnalyze.d.ts +1 -0
  570. package/dist/tools/refactorExtractFunction.js +4 -1
  571. package/dist/tools/refactorExtractFunction.js.map +1 -1
  572. package/dist/tools/refactorPreview.d.ts +1 -0
  573. package/dist/tools/refactorPreview.js +10 -2
  574. package/dist/tools/refactorPreview.js.map +1 -1
  575. package/dist/tools/replaceBlock.d.ts +1 -0
  576. package/dist/tools/replaceBlock.js +2 -1
  577. package/dist/tools/replaceBlock.js.map +1 -1
  578. package/dist/tools/resumeClaudeTask.d.ts +1 -0
  579. package/dist/tools/runClaudeTask.d.ts +1 -0
  580. package/dist/tools/runTests.js +15 -4
  581. package/dist/tools/runTests.js.map +1 -1
  582. package/dist/tools/screenshot.d.ts +1 -0
  583. package/dist/tools/screenshotAndAnnotate.js +6 -2
  584. package/dist/tools/screenshotAndAnnotate.js.map +1 -1
  585. package/dist/tools/searchAndReplace.d.ts +1 -0
  586. package/dist/tools/searchAndReplace.js +17 -7
  587. package/dist/tools/searchAndReplace.js.map +1 -1
  588. package/dist/tools/searchTools.js +20 -19
  589. package/dist/tools/searchTools.js.map +1 -1
  590. package/dist/tools/searchWorkspace.d.ts +1 -0
  591. package/dist/tools/selectionRanges.d.ts +1 -0
  592. package/dist/tools/semanticTokens.d.ts +1 -0
  593. package/dist/tools/signatureHelp.d.ts +1 -0
  594. package/dist/tools/spawnWorkspace.js +15 -7
  595. package/dist/tools/spawnWorkspace.js.map +1 -1
  596. package/dist/tools/terminal.d.ts +6 -0
  597. package/dist/tools/testRunners/pytest.js +6 -2
  598. package/dist/tools/testRunners/pytest.js.map +1 -1
  599. package/dist/tools/testRunners/vitestJest.js +3 -1
  600. package/dist/tools/testRunners/vitestJest.js.map +1 -1
  601. package/dist/tools/testTraceToSource.d.ts +1 -0
  602. package/dist/tools/transaction.d.ts +4 -0
  603. package/dist/tools/transaction.js +4 -1
  604. package/dist/tools/transaction.js.map +1 -1
  605. package/dist/tools/typeHierarchy.d.ts +1 -0
  606. package/dist/tools/utils.d.ts +18 -0
  607. package/dist/tools/utils.js +103 -18
  608. package/dist/tools/utils.js.map +1 -1
  609. package/dist/tools/vscodeCommands.d.ts +2 -0
  610. package/dist/tools/vscodeTasks.d.ts +2 -0
  611. package/dist/tools/workspaceSettings.d.ts +1 -0
  612. package/dist/transport.d.ts +3 -1
  613. package/dist/transport.js +103 -52
  614. package/dist/transport.js.map +1 -1
  615. package/dist/winShim.d.ts +34 -0
  616. package/dist/winShim.js +94 -0
  617. package/dist/winShim.js.map +1 -0
  618. package/dist/wireHaltPushDispatch.d.ts +38 -0
  619. package/dist/wireHaltPushDispatch.js +71 -0
  620. package/dist/wireHaltPushDispatch.js.map +1 -0
  621. package/dist/writeFileAtomic.d.ts +23 -0
  622. package/dist/writeFileAtomic.js +121 -0
  623. package/dist/writeFileAtomic.js.map +1 -0
  624. package/package.json +23 -7
  625. package/scripts/postinstall.mjs +42 -2
  626. package/scripts/smoke/run-all.mjs +213 -0
  627. package/scripts/start-all.mjs +572 -0
  628. package/scripts/start-all.ps1 +209 -0
  629. package/scripts/start-all.sh +73 -17
  630. package/scripts/start-orchestrator.ps1 +158 -0
  631. package/scripts/start-remote.mjs +122 -0
  632. package/templates/automation-policies/recipe-authoring.json +1 -1
  633. package/templates/automation-policies/security-first.json +1 -1
  634. package/templates/automation-policies/strict-lint.json +1 -1
  635. package/templates/automation-policies/test-driven.json +1 -1
  636. package/templates/automation-policy.example.json +1 -1
  637. package/templates/co.patchwork-os.bridge.plist +2 -2
  638. package/templates/recipes/approval-queue-ui-test.yaml +1 -1
  639. package/templates/recipes/ctx-loop-test.yaml +1 -1
  640. package/templates/recipes/fix-errors-on-save.yaml +71 -0
  641. package/templates/recipes/morning-brief.yaml +5 -2
  642. package/templates/recipes/project-health-check.yaml +4 -1
  643. package/templates/recipes/sentry-to-linear.yaml +72 -38
  644. package/templates/recipes/webhook/apple-watch-health-log.yaml +145 -0
  645. package/templates/recipes/webhook/customer-escalation.yaml +8 -9
  646. package/templates/recipes/webhook/meeting-prep.yaml +11 -5
  647. package/dist/commands/marketplace.d.ts +0 -16
  648. package/dist/commands/marketplace.js +0 -32
  649. package/dist/commands/marketplace.js.map +0 -1
  650. package/dist/recipes/legacyRecipeCompat.d.ts +0 -10
  651. package/dist/recipes/legacyRecipeCompat.js +0 -131
  652. package/dist/recipes/legacyRecipeCompat.js.map +0 -1
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Secret reader — file-first, env-fallback.
3
+ *
4
+ * Long-form `_CLIENT_SECRET` / API-token credentials sit in
5
+ * `~/.patchwork/.secrets.json` (a JSON object of `{ NAME: value }` pairs).
6
+ * The helper reads from that file when present and falls back to
7
+ * `process.env[name]` otherwise — so single-bridge users with an env-only
8
+ * setup keep working unchanged, while multi-tenant deployments can mount a
9
+ * read-only secrets file into the tenant volume to keep secrets out of the
10
+ * container's env (visible via `/proc/<pid>/environ`, `printenv`,
11
+ * `docker inspect`, etc.).
12
+ *
13
+ * Format: a single JSON object at `${HOME}/.patchwork/.secrets.json`.
14
+ * {
15
+ * "PATCHWORK_GITHUB_CLIENT_SECRET": "…",
16
+ * "GMAIL_CLIENT_SECRET": "…",
17
+ * "ANTHROPIC_API_KEY": "…"
18
+ * }
19
+ *
20
+ * The file is read once (lazily) and cached in-memory. A successful parse
21
+ * locks the cache for the lifetime of the process — `readFileSync` on every
22
+ * OAuth call would be a perf footgun. Tests that need to swap the file MUST
23
+ * call `_resetSecretsCacheForTests()`.
24
+ *
25
+ * Fail-soft: a missing file, EACCES, malformed JSON, or any read error all
26
+ * route silently to the env-fallback path. We deliberately do NOT log on
27
+ * these — single-bridge installs simply will not have a secrets file, and a
28
+ * noisy warning every connector call would be operator-hostile.
29
+ *
30
+ * Precedence on collision (file present AND env set): the FILE wins. Reasoning:
31
+ * the file path exists exactly to override env. Once a deployment opts into
32
+ * the file by writing it, env values would be stale leftovers (or, worse, the
33
+ * exact leak we are hiding from `/proc/.../environ`). The contract is "file
34
+ * takes over when present", documented here so operators can reason about it.
35
+ */
36
+ /** Absolute path the helper reads from. */
37
+ export declare function secretsFilePath(): string;
38
+ /**
39
+ * Read a named secret. Tries the secrets file first; falls back to
40
+ * `process.env[name]`; returns `""` when neither is set.
41
+ *
42
+ * Returning empty string (not `undefined`) matches the existing `?? ""`
43
+ * pattern at every connector call site — keeps the contract identical so the
44
+ * substitution is a drop-in.
45
+ */
46
+ export declare function readSecret(name: string): string;
47
+ /**
48
+ * Test hook — clears the cached file read so a test can rewrite the secrets
49
+ * file mid-run and observe the new value. Never called in production code.
50
+ */
51
+ export declare function _resetSecretsCacheForTests(): void;
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Secret reader — file-first, env-fallback.
3
+ *
4
+ * Long-form `_CLIENT_SECRET` / API-token credentials sit in
5
+ * `~/.patchwork/.secrets.json` (a JSON object of `{ NAME: value }` pairs).
6
+ * The helper reads from that file when present and falls back to
7
+ * `process.env[name]` otherwise — so single-bridge users with an env-only
8
+ * setup keep working unchanged, while multi-tenant deployments can mount a
9
+ * read-only secrets file into the tenant volume to keep secrets out of the
10
+ * container's env (visible via `/proc/<pid>/environ`, `printenv`,
11
+ * `docker inspect`, etc.).
12
+ *
13
+ * Format: a single JSON object at `${HOME}/.patchwork/.secrets.json`.
14
+ * {
15
+ * "PATCHWORK_GITHUB_CLIENT_SECRET": "…",
16
+ * "GMAIL_CLIENT_SECRET": "…",
17
+ * "ANTHROPIC_API_KEY": "…"
18
+ * }
19
+ *
20
+ * The file is read once (lazily) and cached in-memory. A successful parse
21
+ * locks the cache for the lifetime of the process — `readFileSync` on every
22
+ * OAuth call would be a perf footgun. Tests that need to swap the file MUST
23
+ * call `_resetSecretsCacheForTests()`.
24
+ *
25
+ * Fail-soft: a missing file, EACCES, malformed JSON, or any read error all
26
+ * route silently to the env-fallback path. We deliberately do NOT log on
27
+ * these — single-bridge installs simply will not have a secrets file, and a
28
+ * noisy warning every connector call would be operator-hostile.
29
+ *
30
+ * Precedence on collision (file present AND env set): the FILE wins. Reasoning:
31
+ * the file path exists exactly to override env. Once a deployment opts into
32
+ * the file by writing it, env values would be stale leftovers (or, worse, the
33
+ * exact leak we are hiding from `/proc/.../environ`). The contract is "file
34
+ * takes over when present", documented here so operators can reason about it.
35
+ */
36
+ import { readFileSync } from "node:fs";
37
+ import { homedir } from "node:os";
38
+ import path from "node:path";
39
+ /** Absolute path the helper reads from. */
40
+ export function secretsFilePath() {
41
+ const patchworkHome = process.env.PATCHWORK_HOME ?? path.join(homedir(), ".patchwork");
42
+ return path.join(patchworkHome, ".secrets.json");
43
+ }
44
+ // ── Cache ─────────────────────────────────────────────────────────────────────
45
+ /**
46
+ * Loaded JSON object, or `null` when the file is absent / unreadable /
47
+ * malformed. `undefined` means "not loaded yet". The two distinct states let
48
+ * us only attempt the read once per process — even if the file is missing.
49
+ */
50
+ let cached;
51
+ function load() {
52
+ if (cached !== undefined)
53
+ return cached;
54
+ try {
55
+ const raw = readFileSync(secretsFilePath(), "utf-8");
56
+ const parsed = JSON.parse(raw);
57
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
58
+ // Coerce to Record<string, string>; drop non-string values defensively.
59
+ const out = {};
60
+ for (const [k, v] of Object.entries(parsed)) {
61
+ if (typeof v === "string")
62
+ out[k] = v;
63
+ }
64
+ cached = out;
65
+ return cached;
66
+ }
67
+ cached = null;
68
+ return null;
69
+ }
70
+ catch {
71
+ // ENOENT / EACCES / SyntaxError — silent fallback to env.
72
+ cached = null;
73
+ return null;
74
+ }
75
+ }
76
+ // ── Public API ────────────────────────────────────────────────────────────────
77
+ /**
78
+ * Read a named secret. Tries the secrets file first; falls back to
79
+ * `process.env[name]`; returns `""` when neither is set.
80
+ *
81
+ * Returning empty string (not `undefined`) matches the existing `?? ""`
82
+ * pattern at every connector call site — keeps the contract identical so the
83
+ * substitution is a drop-in.
84
+ */
85
+ export function readSecret(name) {
86
+ const fromFile = load();
87
+ if (fromFile && Object.hasOwn(fromFile, name)) {
88
+ const v = fromFile[name];
89
+ if (typeof v === "string" && v !== "")
90
+ return v;
91
+ // Empty string in the file → still try env (treat the file value as unset).
92
+ }
93
+ return process.env[name] ?? "";
94
+ }
95
+ /**
96
+ * Test hook — clears the cached file read so a test can rewrite the secrets
97
+ * file mid-run and observe the new value. Never called in production code.
98
+ */
99
+ export function _resetSecretsCacheForTests() {
100
+ cached = undefined;
101
+ }
102
+ //# sourceMappingURL=secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/connectors/secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,2CAA2C;AAC3C,MAAM,UAAU,eAAe;IAC7B,MAAM,aAAa,GACjB,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;IACnE,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;AACnD,CAAC;AAED,iFAAiF;AAEjF;;;;GAIG;AACH,IAAI,MAAiD,CAAC;AAEtD,SAAS,IAAI;IACX,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,eAAe,EAAE,EAAE,OAAO,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;QAC1C,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,wEAAwE;YACxE,MAAM,GAAG,GAA2B,EAAE,CAAC;YACvC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAiC,CAAC,EAAE,CAAC;gBACvE,IAAI,OAAO,CAAC,KAAK,QAAQ;oBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACxC,CAAC;YACD,MAAM,GAAG,GAAG,CAAC;YACb,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,MAAM,GAAG,IAAI,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,0DAA0D;QAC1D,MAAM,GAAG,IAAI,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,iFAAiF;AAEjF;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,QAAQ,GAAG,IAAI,EAAE,CAAC;IACxB,IAAI,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC;QAC9C,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,EAAE;YAAE,OAAO,CAAC,CAAC;QAChD,4EAA4E;IAC9E,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,0BAA0B;IACxC,MAAM,GAAG,SAAS,CAAC;AACrB,CAAC"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * SendGrid connector — outbound transactional email via SendGrid v3 REST API.
3
+ *
4
+ * Auth: Bearer API key (`SG.*`).
5
+ * - Env var: SENDGRID_API_KEY (+ optional SENDGRID_FROM_EMAIL)
6
+ * - Stored: getSecretJsonSync("sendgrid") → SendGridTokens
7
+ *
8
+ * Tools: send, listTemplates, getTemplate, listSenders, getStats
9
+ *
10
+ * Extends BaseConnector for unified auth, retry, rate-limit, error handling.
11
+ */
12
+ import { type AuthContext, BaseConnector, type ConnectorError, type ConnectorStatus } from "./baseConnector.js";
13
+ export interface SendGridTokens {
14
+ apiKey: string;
15
+ fromEmail?: string;
16
+ accountName?: string;
17
+ connected_at: string;
18
+ }
19
+ export interface SendGridTemplate {
20
+ id: string;
21
+ name: string;
22
+ generation: "legacy" | "dynamic";
23
+ updated_at?: string;
24
+ }
25
+ export interface SendGridTemplateListResult {
26
+ result: SendGridTemplate[];
27
+ }
28
+ export interface SendGridVerifiedSender {
29
+ id: number;
30
+ from_email: string;
31
+ from_name?: string;
32
+ verified: boolean;
33
+ }
34
+ export interface SendGridSenderListResult {
35
+ results: SendGridVerifiedSender[];
36
+ }
37
+ export interface SendGridStatsBucket {
38
+ date: string;
39
+ stats: Array<{
40
+ metrics: Record<string, number>;
41
+ name?: string;
42
+ type?: string;
43
+ }>;
44
+ }
45
+ export interface SendGridSendResult {
46
+ messageId: string;
47
+ }
48
+ export declare class SendGridConnector extends BaseConnector {
49
+ readonly providerName = "sendgrid";
50
+ private tokens;
51
+ protected getOAuthConfig(): null;
52
+ authenticate(): Promise<AuthContext>;
53
+ healthCheck(): Promise<{
54
+ ok: boolean;
55
+ error?: ConnectorError;
56
+ }>;
57
+ normalizeError(error: unknown): ConnectorError;
58
+ getStatus(): ConnectorStatus;
59
+ send(params: {
60
+ to: string;
61
+ subject: string;
62
+ text?: string;
63
+ html?: string;
64
+ from?: string;
65
+ }): Promise<SendGridSendResult>;
66
+ listTemplates(params?: {
67
+ limit?: number;
68
+ generations?: "legacy" | "dynamic";
69
+ }): Promise<SendGridTemplateListResult>;
70
+ getTemplate(templateId: string): Promise<SendGridTemplate>;
71
+ listSenders(params?: {
72
+ limit?: number;
73
+ }): Promise<SendGridSenderListResult>;
74
+ getStats(params: {
75
+ startDate: string;
76
+ endDate?: string;
77
+ aggregatedBy?: "day" | "week" | "month";
78
+ }): Promise<SendGridStatsBucket[]>;
79
+ private buildHeaders;
80
+ }
81
+ export declare function loadTokens(): SendGridTokens | null;
82
+ export declare function saveTokens(tokens: SendGridTokens): void;
83
+ export declare function clearTokens(): void;
84
+ export declare function getSendGridConnector(): SendGridConnector;
85
+ export { getSendGridConnector as sendgrid };
86
+ export interface ConnectorHandlerResult {
87
+ status: number;
88
+ body: string;
89
+ contentType?: string;
90
+ }
91
+ /**
92
+ * POST /connections/sendgrid/connect { apiKey, fromEmail? }
93
+ */
94
+ export declare function handleSendGridConnect(body: string): Promise<ConnectorHandlerResult>;
95
+ /**
96
+ * POST /connections/sendgrid/test
97
+ */
98
+ export declare function handleSendGridTest(): Promise<ConnectorHandlerResult>;
99
+ /**
100
+ * DELETE /connections/sendgrid
101
+ */
102
+ export declare function handleSendGridDisconnect(): ConnectorHandlerResult;
@@ -0,0 +1,423 @@
1
+ /**
2
+ * SendGrid connector — outbound transactional email via SendGrid v3 REST API.
3
+ *
4
+ * Auth: Bearer API key (`SG.*`).
5
+ * - Env var: SENDGRID_API_KEY (+ optional SENDGRID_FROM_EMAIL)
6
+ * - Stored: getSecretJsonSync("sendgrid") → SendGridTokens
7
+ *
8
+ * Tools: send, listTemplates, getTemplate, listSenders, getStats
9
+ *
10
+ * Extends BaseConnector for unified auth, retry, rate-limit, error handling.
11
+ */
12
+ import { BaseConnector, } from "./baseConnector.js";
13
+ import { deleteSecretJsonSync, getSecretJsonSync, storeSecretJsonSync, } from "./tokenStorage.js";
14
+ const BASE_URL = "https://api.sendgrid.com";
15
+ // Loose RFC 5322-ish email check — good enough to reject obvious garbage.
16
+ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
17
+ function isValidEmail(s) {
18
+ return typeof s === "string" && EMAIL_RE.test(s);
19
+ }
20
+ export class SendGridConnector extends BaseConnector {
21
+ providerName = "sendgrid";
22
+ tokens = null;
23
+ getOAuthConfig() {
24
+ return null;
25
+ }
26
+ async authenticate() {
27
+ const tokens = loadTokens();
28
+ if (!tokens) {
29
+ throw new Error("SendGrid not connected. Run: patchwork-os connect sendgrid or set SENDGRID_API_KEY");
30
+ }
31
+ this.tokens = tokens;
32
+ return {
33
+ token: tokens.apiKey,
34
+ scopes: ["mail.send"],
35
+ };
36
+ }
37
+ async healthCheck() {
38
+ try {
39
+ const result = await this.apiCall(async () => {
40
+ const res = await fetch(`${BASE_URL}/v3/scopes`, {
41
+ headers: this.buildHeaders(),
42
+ });
43
+ if (!res.ok)
44
+ throw res;
45
+ return res.json();
46
+ });
47
+ if ("error" in result)
48
+ return { ok: false, error: result.error };
49
+ return { ok: true };
50
+ }
51
+ catch (err) {
52
+ return { ok: false, error: this.normalizeError(err) };
53
+ }
54
+ }
55
+ normalizeError(error) {
56
+ if (error instanceof Response) {
57
+ const s = error.status;
58
+ if (s === 401)
59
+ return {
60
+ code: "auth_expired",
61
+ message: "SendGrid authentication expired — reconnect",
62
+ retryable: false,
63
+ suggestedAction: "patchwork-os connect sendgrid",
64
+ };
65
+ if (s === 403)
66
+ return {
67
+ code: "permission_denied",
68
+ message: "Insufficient SendGrid permissions",
69
+ retryable: false,
70
+ };
71
+ if (s === 404)
72
+ return {
73
+ code: "not_found",
74
+ message: "SendGrid resource not found",
75
+ retryable: false,
76
+ };
77
+ if (s === 413)
78
+ return {
79
+ code: "provider_error",
80
+ message: "SendGrid payload too large",
81
+ retryable: false,
82
+ };
83
+ if (s === 429)
84
+ return {
85
+ code: "rate_limited",
86
+ message: "SendGrid API rate limit exceeded",
87
+ retryable: true,
88
+ suggestedAction: "Wait and retry",
89
+ };
90
+ if (s >= 500)
91
+ return {
92
+ code: "provider_error",
93
+ message: `SendGrid API error: HTTP ${s}`,
94
+ retryable: true,
95
+ };
96
+ return {
97
+ code: "provider_error",
98
+ message: `SendGrid API error: HTTP ${s}`,
99
+ retryable: false,
100
+ };
101
+ }
102
+ if (error instanceof Error) {
103
+ if (error.message.includes("ENOTFOUND") ||
104
+ error.message.includes("ECONNREFUSED")) {
105
+ return {
106
+ code: "network_error",
107
+ message: `Cannot connect to SendGrid: ${error.message}`,
108
+ retryable: true,
109
+ };
110
+ }
111
+ }
112
+ return {
113
+ code: "provider_error",
114
+ message: error instanceof Error ? error.message : String(error),
115
+ retryable: false,
116
+ };
117
+ }
118
+ getStatus() {
119
+ const tokens = loadTokens();
120
+ return {
121
+ id: "sendgrid",
122
+ status: tokens ? "connected" : "disconnected",
123
+ lastSync: tokens?.connected_at,
124
+ workspace: tokens?.accountName
125
+ ? `SendGrid (${tokens.accountName})`
126
+ : tokens?.fromEmail
127
+ ? `SendGrid <${tokens.fromEmail}>`
128
+ : undefined,
129
+ };
130
+ }
131
+ // ── API Methods ────────────────────────────────────────────────────────────
132
+ async send(params) {
133
+ if (!isValidEmail(params.to)) {
134
+ throw new Error("send: `to` must be a valid email address");
135
+ }
136
+ if (typeof params.subject !== "string" || !params.subject.trim()) {
137
+ throw new Error("send: `subject` is required");
138
+ }
139
+ if (!params.text && !params.html) {
140
+ throw new Error("send: one of `text` or `html` is required");
141
+ }
142
+ const tokens = this.tokens ?? loadTokens();
143
+ const from = params.from ?? tokens?.fromEmail;
144
+ if (!from) {
145
+ throw new Error("send: no `from` provided and no fromEmail stored — pass `from` or reconnect with a verified sender");
146
+ }
147
+ if (!isValidEmail(from)) {
148
+ throw new Error("send: `from` must be a valid email address");
149
+ }
150
+ const content = [];
151
+ if (params.text)
152
+ content.push({ type: "text/plain", value: params.text });
153
+ if (params.html)
154
+ content.push({ type: "text/html", value: params.html });
155
+ const body = {
156
+ personalizations: [{ to: [{ email: params.to }] }],
157
+ from: { email: from },
158
+ subject: params.subject,
159
+ content,
160
+ };
161
+ const result = await this.apiCall(async () => {
162
+ const res = await fetch(`${BASE_URL}/v3/mail/send`, {
163
+ method: "POST",
164
+ headers: {
165
+ ...this.buildHeaders(),
166
+ "Content-Type": "application/json",
167
+ },
168
+ body: JSON.stringify(body),
169
+ });
170
+ if (!res.ok)
171
+ throw res;
172
+ // SendGrid returns 202 + X-Message-Id header on success, empty body.
173
+ const messageId = res.headers.get("x-message-id") ?? "";
174
+ return { messageId };
175
+ });
176
+ if ("error" in result)
177
+ throw new Error(result.error.message);
178
+ return result.data;
179
+ }
180
+ async listTemplates(params = {}) {
181
+ const result = await this.apiCall(async () => {
182
+ const qs = new URLSearchParams();
183
+ if (params.limit)
184
+ qs.set("page_size", String(params.limit));
185
+ if (params.generations)
186
+ qs.set("generations", params.generations);
187
+ const url = `${BASE_URL}/v3/templates${qs.toString() ? `?${qs}` : ""}`;
188
+ const res = await fetch(url, { headers: this.buildHeaders() });
189
+ if (!res.ok)
190
+ throw res;
191
+ return res.json();
192
+ });
193
+ if ("error" in result)
194
+ throw new Error(result.error.message);
195
+ return result.data;
196
+ }
197
+ async getTemplate(templateId) {
198
+ if (!templateId || typeof templateId !== "string") {
199
+ throw new Error("getTemplate: templateId is required");
200
+ }
201
+ const result = await this.apiCall(async () => {
202
+ const res = await fetch(`${BASE_URL}/v3/templates/${encodeURIComponent(templateId)}`, { headers: this.buildHeaders() });
203
+ if (!res.ok)
204
+ throw res;
205
+ return res.json();
206
+ });
207
+ if ("error" in result)
208
+ throw new Error(result.error.message);
209
+ return result.data;
210
+ }
211
+ async listSenders(params = {}) {
212
+ const result = await this.apiCall(async () => {
213
+ const qs = new URLSearchParams();
214
+ if (params.limit)
215
+ qs.set("limit", String(params.limit));
216
+ const url = `${BASE_URL}/v3/verified_senders${qs.toString() ? `?${qs}` : ""}`;
217
+ const res = await fetch(url, { headers: this.buildHeaders() });
218
+ if (!res.ok)
219
+ throw res;
220
+ return res.json();
221
+ });
222
+ if ("error" in result)
223
+ throw new Error(result.error.message);
224
+ return result.data;
225
+ }
226
+ async getStats(params) {
227
+ if (!params.startDate) {
228
+ throw new Error("getStats: startDate is required (YYYY-MM-DD)");
229
+ }
230
+ const result = await this.apiCall(async () => {
231
+ const qs = new URLSearchParams();
232
+ qs.set("start_date", params.startDate);
233
+ if (params.endDate)
234
+ qs.set("end_date", params.endDate);
235
+ if (params.aggregatedBy)
236
+ qs.set("aggregated_by", params.aggregatedBy);
237
+ const res = await fetch(`${BASE_URL}/v3/stats?${qs}`, {
238
+ headers: this.buildHeaders(),
239
+ });
240
+ if (!res.ok)
241
+ throw res;
242
+ return res.json();
243
+ });
244
+ if ("error" in result)
245
+ throw new Error(result.error.message);
246
+ return result.data;
247
+ }
248
+ // ── Helpers ────────────────────────────────────────────────────────────────
249
+ buildHeaders() {
250
+ const key = this.tokens?.apiKey ?? loadTokens()?.apiKey ?? "";
251
+ return {
252
+ Authorization: `Bearer ${key}`,
253
+ Accept: "application/json",
254
+ };
255
+ }
256
+ }
257
+ // ── Token persistence ────────────────────────────────────────────────────────
258
+ export function loadTokens() {
259
+ const envKey = process.env.SENDGRID_API_KEY;
260
+ if (envKey) {
261
+ return {
262
+ apiKey: envKey,
263
+ fromEmail: process.env.SENDGRID_FROM_EMAIL,
264
+ connected_at: new Date().toISOString(),
265
+ };
266
+ }
267
+ return getSecretJsonSync("sendgrid");
268
+ }
269
+ export function saveTokens(tokens) {
270
+ storeSecretJsonSync("sendgrid", tokens);
271
+ }
272
+ export function clearTokens() {
273
+ try {
274
+ deleteSecretJsonSync("sendgrid");
275
+ }
276
+ catch {
277
+ // ignore
278
+ }
279
+ }
280
+ // ── Singleton instance ───────────────────────────────────────────────────────
281
+ let _instance = null;
282
+ function resetSendGridConnector() {
283
+ _instance = null;
284
+ }
285
+ export function getSendGridConnector() {
286
+ if (!_instance) {
287
+ _instance = new SendGridConnector();
288
+ }
289
+ return _instance;
290
+ }
291
+ export { getSendGridConnector as sendgrid };
292
+ /**
293
+ * POST /connections/sendgrid/connect { apiKey, fromEmail? }
294
+ */
295
+ export async function handleSendGridConnect(body) {
296
+ let apiKey;
297
+ let fromEmail;
298
+ try {
299
+ const parsed = JSON.parse(body);
300
+ if (typeof parsed.apiKey !== "string" || !parsed.apiKey) {
301
+ return {
302
+ status: 400,
303
+ contentType: "application/json",
304
+ body: JSON.stringify({ ok: false, error: "apiKey is required" }),
305
+ };
306
+ }
307
+ apiKey = parsed.apiKey;
308
+ if (parsed.fromEmail !== undefined) {
309
+ if (typeof parsed.fromEmail !== "string" ||
310
+ !isValidEmail(parsed.fromEmail)) {
311
+ return {
312
+ status: 400,
313
+ contentType: "application/json",
314
+ body: JSON.stringify({
315
+ ok: false,
316
+ error: "fromEmail must be a valid email address",
317
+ }),
318
+ };
319
+ }
320
+ fromEmail = parsed.fromEmail;
321
+ }
322
+ }
323
+ catch {
324
+ return {
325
+ status: 400,
326
+ contentType: "application/json",
327
+ body: JSON.stringify({ ok: false, error: "Invalid JSON body" }),
328
+ };
329
+ }
330
+ try {
331
+ const res = await fetch(`${BASE_URL}/v3/user/profile`, {
332
+ headers: {
333
+ Authorization: `Bearer ${apiKey}`,
334
+ Accept: "application/json",
335
+ },
336
+ });
337
+ if (!res.ok) {
338
+ return {
339
+ status: 401,
340
+ contentType: "application/json",
341
+ body: JSON.stringify({
342
+ ok: false,
343
+ error: `Credentials rejected by SendGrid (HTTP ${res.status}) — check apiKey`,
344
+ }),
345
+ };
346
+ }
347
+ const profile = (await res.json());
348
+ const accountName = profile.username ?? undefined;
349
+ const tokens = {
350
+ apiKey,
351
+ fromEmail,
352
+ accountName,
353
+ connected_at: new Date().toISOString(),
354
+ };
355
+ saveTokens(tokens);
356
+ resetSendGridConnector();
357
+ return {
358
+ status: 200,
359
+ contentType: "application/json",
360
+ body: JSON.stringify({
361
+ ok: true,
362
+ accountName,
363
+ fromEmail,
364
+ connectedAt: tokens.connected_at,
365
+ }),
366
+ };
367
+ }
368
+ catch (err) {
369
+ return {
370
+ status: 500,
371
+ contentType: "application/json",
372
+ body: JSON.stringify({
373
+ ok: false,
374
+ error: err instanceof Error ? err.message : String(err),
375
+ }),
376
+ };
377
+ }
378
+ }
379
+ /**
380
+ * POST /connections/sendgrid/test
381
+ */
382
+ export async function handleSendGridTest() {
383
+ const tokens = loadTokens();
384
+ if (!tokens) {
385
+ return {
386
+ status: 400,
387
+ contentType: "application/json",
388
+ body: JSON.stringify({ ok: false, error: "SendGrid not connected" }),
389
+ };
390
+ }
391
+ try {
392
+ const connector = getSendGridConnector();
393
+ const check = await connector.healthCheck();
394
+ return {
395
+ status: check.ok ? 200 : 401,
396
+ contentType: "application/json",
397
+ body: JSON.stringify(check.ok ? { ok: true } : { ok: false, error: check.error?.message }),
398
+ };
399
+ }
400
+ catch (err) {
401
+ return {
402
+ status: 500,
403
+ contentType: "application/json",
404
+ body: JSON.stringify({
405
+ ok: false,
406
+ error: err instanceof Error ? err.message : String(err),
407
+ }),
408
+ };
409
+ }
410
+ }
411
+ /**
412
+ * DELETE /connections/sendgrid
413
+ */
414
+ export function handleSendGridDisconnect() {
415
+ clearTokens();
416
+ resetSendGridConnector();
417
+ return {
418
+ status: 200,
419
+ contentType: "application/json",
420
+ body: JSON.stringify({ ok: true }),
421
+ };
422
+ }
423
+ //# sourceMappingURL=sendgrid.js.map