narai-primitives 2.1.3 → 2.2.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 (389) hide show
  1. package/README.md +16 -4
  2. package/dist/config/load.d.ts.map +1 -1
  3. package/dist/config/load.js +12 -1
  4. package/dist/config/load.js.map +1 -1
  5. package/dist/connectors/confluence/index.d.ts +3 -1
  6. package/dist/connectors/confluence/index.d.ts.map +1 -1
  7. package/dist/connectors/confluence/index.js +246 -31
  8. package/dist/connectors/confluence/index.js.map +1 -1
  9. package/dist/connectors/confluence/lib/confluence_client.d.ts +50 -30
  10. package/dist/connectors/confluence/lib/confluence_client.d.ts.map +1 -1
  11. package/dist/connectors/confluence/lib/confluence_client.js +69 -225
  12. package/dist/connectors/confluence/lib/confluence_client.js.map +1 -1
  13. package/dist/connectors/db/connector.d.ts.map +1 -1
  14. package/dist/connectors/db/connector.js +12 -6
  15. package/dist/connectors/db/connector.js.map +1 -1
  16. package/dist/connectors/db/dispatcher.d.ts +3 -2
  17. package/dist/connectors/db/dispatcher.d.ts.map +1 -1
  18. package/dist/connectors/db/dispatcher.js +136 -40
  19. package/dist/connectors/db/dispatcher.js.map +1 -1
  20. package/dist/connectors/db/index.d.ts +9 -0
  21. package/dist/connectors/db/index.d.ts.map +1 -1
  22. package/dist/connectors/db/index.js +9 -0
  23. package/dist/connectors/db/index.js.map +1 -1
  24. package/dist/connectors/db/lib/audit.d.ts.map +1 -1
  25. package/dist/connectors/db/lib/audit.js +46 -4
  26. package/dist/connectors/db/lib/audit.js.map +1 -1
  27. package/dist/connectors/db/lib/drivers/dynamodb.d.ts.map +1 -1
  28. package/dist/connectors/db/lib/drivers/dynamodb.js +24 -4
  29. package/dist/connectors/db/lib/drivers/dynamodb.js.map +1 -1
  30. package/dist/connectors/db/lib/drivers/mysql.js +1 -1
  31. package/dist/connectors/db/lib/drivers/mysql.js.map +1 -1
  32. package/dist/connectors/db/lib/drivers/postgresql.js +1 -1
  33. package/dist/connectors/db/lib/drivers/postgresql.js.map +1 -1
  34. package/dist/connectors/db/lib/drivers/sqlite.d.ts.map +1 -1
  35. package/dist/connectors/db/lib/drivers/sqlite.js +9 -5
  36. package/dist/connectors/db/lib/drivers/sqlite.js.map +1 -1
  37. package/dist/connectors/db/lib/drivers/sqlserver.d.ts.map +1 -1
  38. package/dist/connectors/db/lib/drivers/sqlserver.js +66 -32
  39. package/dist/connectors/db/lib/drivers/sqlserver.js.map +1 -1
  40. package/dist/connectors/db/lib/environments.d.ts +16 -0
  41. package/dist/connectors/db/lib/environments.d.ts.map +1 -1
  42. package/dist/connectors/db/lib/environments.js +16 -0
  43. package/dist/connectors/db/lib/environments.js.map +1 -1
  44. package/dist/connectors/db/lib/grant-store.d.ts +70 -0
  45. package/dist/connectors/db/lib/grant-store.d.ts.map +1 -0
  46. package/dist/connectors/db/lib/grant-store.js +149 -0
  47. package/dist/connectors/db/lib/grant-store.js.map +1 -0
  48. package/dist/connectors/db/lib/plugin_config.d.ts +2 -0
  49. package/dist/connectors/db/lib/plugin_config.d.ts.map +1 -1
  50. package/dist/connectors/db/lib/plugin_config.js +23 -2
  51. package/dist/connectors/db/lib/plugin_config.js.map +1 -1
  52. package/dist/connectors/db/lib/policy.d.ts +50 -14
  53. package/dist/connectors/db/lib/policy.d.ts.map +1 -1
  54. package/dist/connectors/db/lib/policy.js +295 -73
  55. package/dist/connectors/db/lib/policy.js.map +1 -1
  56. package/dist/connectors/github/actions/_fields.d.ts +18 -0
  57. package/dist/connectors/github/actions/_fields.d.ts.map +1 -0
  58. package/dist/connectors/github/actions/_fields.js +29 -0
  59. package/dist/connectors/github/actions/_fields.js.map +1 -0
  60. package/dist/connectors/github/actions/_pagination.d.ts +12 -0
  61. package/dist/connectors/github/actions/_pagination.d.ts.map +1 -0
  62. package/dist/connectors/github/actions/_pagination.js +26 -0
  63. package/dist/connectors/github/actions/_pagination.js.map +1 -0
  64. package/dist/connectors/github/actions/_types.d.ts +14 -0
  65. package/dist/connectors/github/actions/_types.d.ts.map +1 -0
  66. package/dist/connectors/github/actions/_types.js +2 -0
  67. package/dist/connectors/github/actions/_types.js.map +1 -0
  68. package/dist/connectors/github/actions/comments.d.ts +3 -0
  69. package/dist/connectors/github/actions/comments.d.ts.map +1 -0
  70. package/dist/connectors/github/actions/comments.js +166 -0
  71. package/dist/connectors/github/actions/comments.js.map +1 -0
  72. package/dist/connectors/github/actions/issues.d.ts +3 -0
  73. package/dist/connectors/github/actions/issues.d.ts.map +1 -0
  74. package/dist/connectors/github/actions/issues.js +129 -0
  75. package/dist/connectors/github/actions/issues.js.map +1 -0
  76. package/dist/connectors/github/actions/pulls.d.ts +3 -0
  77. package/dist/connectors/github/actions/pulls.d.ts.map +1 -0
  78. package/dist/connectors/github/actions/pulls.js +182 -0
  79. package/dist/connectors/github/actions/pulls.js.map +1 -0
  80. package/dist/connectors/github/actions/reads.d.ts +3 -0
  81. package/dist/connectors/github/actions/reads.d.ts.map +1 -0
  82. package/dist/connectors/github/actions/reads.js +349 -0
  83. package/dist/connectors/github/actions/reads.js.map +1 -0
  84. package/dist/connectors/github/actions/releases.d.ts +3 -0
  85. package/dist/connectors/github/actions/releases.d.ts.map +1 -0
  86. package/dist/connectors/github/actions/releases.js +124 -0
  87. package/dist/connectors/github/actions/releases.js.map +1 -0
  88. package/dist/connectors/github/actions/workflows.d.ts +3 -0
  89. package/dist/connectors/github/actions/workflows.d.ts.map +1 -0
  90. package/dist/connectors/github/actions/workflows.js +224 -0
  91. package/dist/connectors/github/actions/workflows.js.map +1 -0
  92. package/dist/connectors/github/index.d.ts +13 -1
  93. package/dist/connectors/github/index.d.ts.map +1 -1
  94. package/dist/connectors/github/index.js +33 -396
  95. package/dist/connectors/github/index.js.map +1 -1
  96. package/dist/connectors/github/lib/github_client.d.ts +242 -29
  97. package/dist/connectors/github/lib/github_client.d.ts.map +1 -1
  98. package/dist/connectors/github/lib/github_client.js +202 -256
  99. package/dist/connectors/github/lib/github_client.js.map +1 -1
  100. package/dist/connectors/github/lib/github_config.d.ts +10 -0
  101. package/dist/connectors/github/lib/github_config.d.ts.map +1 -0
  102. package/dist/connectors/github/lib/github_config.js +79 -0
  103. package/dist/connectors/github/lib/github_config.js.map +1 -0
  104. package/dist/connectors/gitlab/actions/_fields.d.ts +20 -0
  105. package/dist/connectors/gitlab/actions/_fields.d.ts.map +1 -0
  106. package/dist/connectors/gitlab/actions/_fields.js +44 -0
  107. package/dist/connectors/gitlab/actions/_fields.js.map +1 -0
  108. package/dist/connectors/gitlab/actions/_pagination.d.ts +19 -0
  109. package/dist/connectors/gitlab/actions/_pagination.d.ts.map +1 -0
  110. package/dist/connectors/gitlab/actions/_pagination.js +33 -0
  111. package/dist/connectors/gitlab/actions/_pagination.js.map +1 -0
  112. package/dist/connectors/gitlab/actions/_types.d.ts +12 -0
  113. package/dist/connectors/gitlab/actions/_types.d.ts.map +1 -0
  114. package/dist/connectors/gitlab/actions/_types.js +2 -0
  115. package/dist/connectors/gitlab/actions/_types.js.map +1 -0
  116. package/dist/connectors/gitlab/actions/issues.d.ts +3 -0
  117. package/dist/connectors/gitlab/actions/issues.d.ts.map +1 -0
  118. package/dist/connectors/gitlab/actions/issues.js +119 -0
  119. package/dist/connectors/gitlab/actions/issues.js.map +1 -0
  120. package/dist/connectors/gitlab/actions/merges.d.ts +3 -0
  121. package/dist/connectors/gitlab/actions/merges.d.ts.map +1 -0
  122. package/dist/connectors/gitlab/actions/merges.js +198 -0
  123. package/dist/connectors/gitlab/actions/merges.js.map +1 -0
  124. package/dist/connectors/gitlab/actions/notes.d.ts +3 -0
  125. package/dist/connectors/gitlab/actions/notes.d.ts.map +1 -0
  126. package/dist/connectors/gitlab/actions/notes.js +145 -0
  127. package/dist/connectors/gitlab/actions/notes.js.map +1 -0
  128. package/dist/connectors/gitlab/actions/pipelines.d.ts +3 -0
  129. package/dist/connectors/gitlab/actions/pipelines.d.ts.map +1 -0
  130. package/dist/connectors/gitlab/actions/pipelines.js +136 -0
  131. package/dist/connectors/gitlab/actions/pipelines.js.map +1 -0
  132. package/dist/connectors/gitlab/actions/reads.d.ts +3 -0
  133. package/dist/connectors/gitlab/actions/reads.d.ts.map +1 -0
  134. package/dist/connectors/gitlab/actions/reads.js +422 -0
  135. package/dist/connectors/gitlab/actions/reads.js.map +1 -0
  136. package/dist/connectors/gitlab/actions/releases.d.ts +3 -0
  137. package/dist/connectors/gitlab/actions/releases.d.ts.map +1 -0
  138. package/dist/connectors/gitlab/actions/releases.js +99 -0
  139. package/dist/connectors/gitlab/actions/releases.js.map +1 -0
  140. package/dist/connectors/gitlab/cli.d.ts +3 -0
  141. package/dist/connectors/gitlab/cli.d.ts.map +1 -0
  142. package/dist/connectors/gitlab/cli.js +24 -0
  143. package/dist/connectors/gitlab/cli.js.map +1 -0
  144. package/dist/connectors/gitlab/index.d.ts +29 -0
  145. package/dist/connectors/gitlab/index.d.ts.map +1 -0
  146. package/dist/connectors/gitlab/index.js +95 -0
  147. package/dist/connectors/gitlab/index.js.map +1 -0
  148. package/dist/connectors/gitlab/lib/gitlab_client.d.ts +306 -0
  149. package/dist/connectors/gitlab/lib/gitlab_client.d.ts.map +1 -0
  150. package/dist/connectors/gitlab/lib/gitlab_client.js +249 -0
  151. package/dist/connectors/gitlab/lib/gitlab_client.js.map +1 -0
  152. package/dist/connectors/gitlab/lib/gitlab_config.d.ts +11 -0
  153. package/dist/connectors/gitlab/lib/gitlab_config.d.ts.map +1 -0
  154. package/dist/connectors/gitlab/lib/gitlab_config.js +115 -0
  155. package/dist/connectors/gitlab/lib/gitlab_config.js.map +1 -0
  156. package/dist/connectors/jira/index.d.ts +3 -1
  157. package/dist/connectors/jira/index.d.ts.map +1 -1
  158. package/dist/connectors/jira/index.js +299 -41
  159. package/dist/connectors/jira/index.js.map +1 -1
  160. package/dist/connectors/jira/lib/jira_client.d.ts +56 -41
  161. package/dist/connectors/jira/lib/jira_client.d.ts.map +1 -1
  162. package/dist/connectors/jira/lib/jira_client.js +71 -248
  163. package/dist/connectors/jira/lib/jira_client.js.map +1 -1
  164. package/dist/connectors/linear/cli.d.ts +3 -0
  165. package/dist/connectors/linear/cli.d.ts.map +1 -0
  166. package/dist/connectors/linear/cli.js +22 -0
  167. package/dist/connectors/linear/cli.js.map +1 -0
  168. package/dist/connectors/linear/index.d.ts +27 -0
  169. package/dist/connectors/linear/index.d.ts.map +1 -0
  170. package/dist/connectors/linear/index.js +496 -0
  171. package/dist/connectors/linear/index.js.map +1 -0
  172. package/dist/connectors/linear/lib/linear_client.d.ts +249 -0
  173. package/dist/connectors/linear/lib/linear_client.d.ts.map +1 -0
  174. package/dist/connectors/linear/lib/linear_client.js +154 -0
  175. package/dist/connectors/linear/lib/linear_client.js.map +1 -0
  176. package/dist/connectors/linear/lib/queries.d.ts +15 -0
  177. package/dist/connectors/linear/lib/queries.d.ts.map +1 -0
  178. package/dist/connectors/linear/lib/queries.js +188 -0
  179. package/dist/connectors/linear/lib/queries.js.map +1 -0
  180. package/dist/connectors/notion/index.d.ts +2 -1
  181. package/dist/connectors/notion/index.d.ts.map +1 -1
  182. package/dist/connectors/notion/index.js +213 -28
  183. package/dist/connectors/notion/index.js.map +1 -1
  184. package/dist/connectors/notion/lib/markdown_to_blocks.d.ts +21 -0
  185. package/dist/connectors/notion/lib/markdown_to_blocks.d.ts.map +1 -0
  186. package/dist/connectors/notion/lib/markdown_to_blocks.js +102 -0
  187. package/dist/connectors/notion/lib/markdown_to_blocks.js.map +1 -0
  188. package/dist/connectors/notion/lib/notion_blocks.d.ts +34 -0
  189. package/dist/connectors/notion/lib/notion_blocks.d.ts.map +1 -0
  190. package/dist/connectors/notion/lib/notion_blocks.js +87 -0
  191. package/dist/connectors/notion/lib/notion_blocks.js.map +1 -0
  192. package/dist/connectors/notion/lib/notion_client.d.ts +35 -25
  193. package/dist/connectors/notion/lib/notion_client.d.ts.map +1 -1
  194. package/dist/connectors/notion/lib/notion_client.js +63 -185
  195. package/dist/connectors/notion/lib/notion_client.js.map +1 -1
  196. package/dist/hub/index.d.ts.map +1 -1
  197. package/dist/hub/index.js +23 -3
  198. package/dist/hub/index.js.map +1 -1
  199. package/dist/toolkit/agent_resolver.d.ts +14 -4
  200. package/dist/toolkit/agent_resolver.d.ts.map +1 -1
  201. package/dist/toolkit/agent_resolver.js +38 -6
  202. package/dist/toolkit/agent_resolver.js.map +1 -1
  203. package/dist/toolkit/atlassian/adf_validator.d.ts +45 -0
  204. package/dist/toolkit/atlassian/adf_validator.d.ts.map +1 -0
  205. package/dist/toolkit/atlassian/adf_validator.js +83 -0
  206. package/dist/toolkit/atlassian/adf_validator.js.map +1 -0
  207. package/dist/toolkit/atlassian/index.d.ts +5 -0
  208. package/dist/toolkit/atlassian/index.d.ts.map +1 -0
  209. package/dist/toolkit/atlassian/index.js +5 -0
  210. package/dist/toolkit/atlassian/index.js.map +1 -0
  211. package/dist/toolkit/audit/writer.d.ts.map +1 -1
  212. package/dist/toolkit/audit/writer.js +45 -5
  213. package/dist/toolkit/audit/writer.js.map +1 -1
  214. package/dist/toolkit/connector_error.d.ts +12 -0
  215. package/dist/toolkit/connector_error.d.ts.map +1 -0
  216. package/dist/toolkit/connector_error.js +18 -0
  217. package/dist/toolkit/connector_error.js.map +1 -0
  218. package/dist/toolkit/guardrail.d.ts +12 -2
  219. package/dist/toolkit/guardrail.d.ts.map +1 -1
  220. package/dist/toolkit/guardrail.js +17 -3
  221. package/dist/toolkit/guardrail.js.map +1 -1
  222. package/dist/toolkit/http_client.d.ts +134 -0
  223. package/dist/toolkit/http_client.d.ts.map +1 -0
  224. package/dist/toolkit/http_client.js +385 -0
  225. package/dist/toolkit/http_client.js.map +1 -0
  226. package/dist/toolkit/index.d.ts +3 -0
  227. package/dist/toolkit/index.d.ts.map +1 -1
  228. package/dist/toolkit/index.js +5 -0
  229. package/dist/toolkit/index.js.map +1 -1
  230. package/dist/toolkit/usage/aggregate.d.ts.map +1 -1
  231. package/dist/toolkit/usage/aggregate.js +19 -3
  232. package/dist/toolkit/usage/aggregate.js.map +1 -1
  233. package/package.json +14 -2
  234. package/plugin-hooks/dispatcher.mjs +584 -0
  235. package/plugin-hooks/plugin-config.mjs +36 -0
  236. package/plugins/{aws-agent → aws-connector}/.claude-plugin/plugin.json +1 -1
  237. package/plugins/{aws-agent → aws-connector}/README.md +7 -7
  238. package/plugins/{aws-agent/bin/aws-agent → aws-connector/bin/aws-connector} +3 -3
  239. package/plugins/aws-connector/commands/aws-connector.md +6 -0
  240. package/plugins/{gcp-agent → aws-connector}/hooks/hooks.json +12 -11
  241. package/plugins/aws-connector/package.json +9 -0
  242. package/plugins/aws-connector/plugin-config.json +4 -0
  243. package/plugins/{aws-agent/skills/aws-agent → aws-connector/skills/aws-connector}/SKILL.md +5 -5
  244. package/plugins/confluence-connector/.claude-plugin/plugin.json +6 -0
  245. package/plugins/{confluence-agent → confluence-connector}/README.md +2 -2
  246. package/plugins/confluence-connector/bin/confluence-connector +17 -0
  247. package/plugins/confluence-connector/commands/confluence-connector.md +6 -0
  248. package/plugins/{jira-agent → confluence-connector}/hooks/hooks.json +12 -11
  249. package/plugins/confluence-connector/package.json +8 -0
  250. package/plugins/confluence-connector/plugin-config.json +4 -0
  251. package/plugins/confluence-connector/skills/confluence-connector/SKILL.md +146 -0
  252. package/plugins/{create-connector → connector-creator}/.claude-plugin/plugin.json +1 -1
  253. package/plugins/{create-connector → connector-creator}/README.md +2 -2
  254. package/plugins/connector-creator/skills/connector-creator/SKILL.md +412 -0
  255. package/plugins/connector-creator/skills/connector-creator/assets/templates/_runtime/connector-gate.mjs.tmpl +120 -0
  256. package/plugins/connector-creator/skills/connector-creator/assets/templates/composite/SKILL.md.tmpl +26 -0
  257. package/plugins/connector-creator/skills/connector-creator/assets/templates/composite/bin.tmpl +2 -0
  258. package/plugins/connector-creator/skills/connector-creator/assets/templates/composite/index.mjs.tmpl +35 -0
  259. package/plugins/connector-creator/skills/connector-creator/assets/templates/knowledge/SKILL.md.tmpl +23 -0
  260. package/plugins/connector-creator/skills/connector-creator/assets/templates/shell-gate/SKILL.md.tmpl +27 -0
  261. package/plugins/connector-creator/skills/connector-creator/assets/templates/shell-gate/gates.json.tmpl +5 -0
  262. package/plugins/connector-creator/skills/connector-creator/lib/connector-registry.mjs +43 -0
  263. package/plugins/connector-creator/skills/connector-creator/lib/settings-wiring.mjs +71 -0
  264. package/plugins/connector-creator/skills/connector-creator/references/connector-contract.md +79 -0
  265. package/plugins/connector-creator/skills/connector-creator/references/flavor-authoring.md +58 -0
  266. package/plugins/connector-creator/skills/connector-creator/references/research-patterns.md +51 -0
  267. package/plugins/{db-agent → db-connector}/.claude-plugin/plugin.json +3 -3
  268. package/plugins/{db-agent → db-connector}/README.md +2 -2
  269. package/plugins/{github-agent/bin/github-agent → db-connector/bin/db-connector} +3 -3
  270. package/plugins/db-connector/commands/db-connector.md +6 -0
  271. package/plugins/db-connector/gates.json +37 -0
  272. package/plugins/{db-agent → db-connector}/hooks/guardrails.json +4 -2
  273. package/plugins/{aws-agent → db-connector}/hooks/hooks.json +15 -11
  274. package/plugins/{db-agent → db-connector}/package.json +1 -1
  275. package/plugins/db-connector/plugin-config.json +5 -0
  276. package/plugins/{db-agent/skills/db-agent → db-connector/skills/db-connector}/SKILL.md +5 -5
  277. package/plugins/{gcp-agent → gcp-connector}/.claude-plugin/plugin.json +1 -1
  278. package/plugins/{gcp-agent → gcp-connector}/README.md +5 -5
  279. package/plugins/{gcp-agent/bin/gcp-agent → gcp-connector/bin/gcp-connector} +3 -3
  280. package/plugins/gcp-connector/commands/gcp-connector.md +6 -0
  281. package/plugins/{github-agent → gcp-connector}/hooks/hooks.json +12 -11
  282. package/plugins/gcp-connector/package.json +9 -0
  283. package/plugins/gcp-connector/plugin-config.json +4 -0
  284. package/plugins/{gcp-agent/skills/gcp-agent → gcp-connector/skills/gcp-connector}/SKILL.md +5 -5
  285. package/plugins/git-connector/.claude-plugin/plugin.json +6 -0
  286. package/plugins/git-connector/CONTRIBUTING.md +117 -0
  287. package/plugins/git-connector/README.md +94 -0
  288. package/plugins/git-connector/SECURITY.md +143 -0
  289. package/plugins/git-connector/gates.json +54 -0
  290. package/plugins/git-connector/hooks/hooks.json +25 -0
  291. package/plugins/git-connector/package.json +9 -0
  292. package/plugins/git-connector/plugin-config.json +4 -0
  293. package/plugins/{github-agent → github-connector}/.claude-plugin/plugin.json +1 -1
  294. package/plugins/github-connector/README.md +48 -0
  295. package/plugins/{confluence-agent/bin/confluence-agent → github-connector/bin/github-connector} +3 -3
  296. package/plugins/github-connector/commands/github-connector.md +6 -0
  297. package/plugins/github-connector/hooks/hooks.json +50 -0
  298. package/plugins/{jira-agent → github-connector}/package.json +1 -1
  299. package/plugins/github-connector/plugin-config.json +4 -0
  300. package/plugins/github-connector/skills/github-connector/SKILL.md +106 -0
  301. package/plugins/gitlab-connector/.claude-plugin/plugin.json +6 -0
  302. package/plugins/gitlab-connector/README.md +62 -0
  303. package/plugins/{db-agent/bin/db-agent → gitlab-connector/bin/gitlab-connector} +3 -3
  304. package/plugins/gitlab-connector/commands/gitlab-connector.md +6 -0
  305. package/plugins/gitlab-connector/hooks/hooks.json +50 -0
  306. package/plugins/{confluence-agent → gitlab-connector}/package.json +1 -1
  307. package/plugins/gitlab-connector/plugin-config.json +4 -0
  308. package/plugins/gitlab-connector/skills/gitlab-connector/SKILL.md +115 -0
  309. package/plugins/jira-connector/.claude-plugin/plugin.json +6 -0
  310. package/plugins/{jira-agent → jira-connector}/README.md +1 -1
  311. package/plugins/{jira-agent/bin/jira-agent → jira-connector/bin/jira-connector} +2 -2
  312. package/plugins/jira-connector/commands/jira-connector.md +6 -0
  313. package/plugins/jira-connector/hooks/hooks.json +50 -0
  314. package/plugins/{github-agent → jira-connector}/package.json +1 -1
  315. package/plugins/jira-connector/plugin-config.json +4 -0
  316. package/plugins/jira-connector/skills/jira-connector/SKILL.md +146 -0
  317. package/plugins/linear-connector/.claude-plugin/plugin.json +6 -0
  318. package/plugins/linear-connector/README.md +29 -0
  319. package/plugins/linear-connector/bin/linear-connector +17 -0
  320. package/plugins/linear-connector/commands/linear-connector.md +6 -0
  321. package/plugins/linear-connector/hooks/hooks.json +50 -0
  322. package/plugins/linear-connector/package.json +8 -0
  323. package/plugins/linear-connector/plugin-config.json +4 -0
  324. package/plugins/linear-connector/skills/linear-connector/SKILL.md +159 -0
  325. package/plugins/notion-connector/.claude-plugin/plugin.json +6 -0
  326. package/plugins/{notion-agent → notion-connector}/README.md +5 -5
  327. package/plugins/{notion-agent/bin/notion-agent → notion-connector/bin/notion-connector} +2 -2
  328. package/plugins/notion-connector/commands/notion-connector.md +6 -0
  329. package/plugins/notion-connector/hooks/hooks.json +50 -0
  330. package/plugins/notion-connector/package.json +8 -0
  331. package/plugins/notion-connector/plugin-config.json +4 -0
  332. package/plugins/notion-connector/skills/notion-connector/SKILL.md +141 -0
  333. package/dist/connectors/confluence/lib/confluence_error.d.ts +0 -13
  334. package/dist/connectors/confluence/lib/confluence_error.d.ts.map +0 -1
  335. package/dist/connectors/confluence/lib/confluence_error.js +0 -19
  336. package/dist/connectors/confluence/lib/confluence_error.js.map +0 -1
  337. package/dist/connectors/github/lib/github_error.d.ts +0 -11
  338. package/dist/connectors/github/lib/github_error.d.ts.map +0 -1
  339. package/dist/connectors/github/lib/github_error.js +0 -17
  340. package/dist/connectors/github/lib/github_error.js.map +0 -1
  341. package/dist/connectors/jira/lib/jira_error.d.ts +0 -11
  342. package/dist/connectors/jira/lib/jira_error.d.ts.map +0 -1
  343. package/dist/connectors/jira/lib/jira_error.js +0 -17
  344. package/dist/connectors/jira/lib/jira_error.js.map +0 -1
  345. package/dist/connectors/notion/lib/notion_error.d.ts +0 -12
  346. package/dist/connectors/notion/lib/notion_error.d.ts.map +0 -1
  347. package/dist/connectors/notion/lib/notion_error.js +0 -18
  348. package/dist/connectors/notion/lib/notion_error.js.map +0 -1
  349. package/plugins/aws-agent/commands/aws-agent.md +0 -6
  350. package/plugins/aws-agent/hooks/reminder.mjs +0 -16
  351. package/plugins/aws-agent/package.json +0 -9
  352. package/plugins/confluence-agent/.claude-plugin/plugin.json +0 -6
  353. package/plugins/confluence-agent/commands/confluence-agent.md +0 -6
  354. package/plugins/confluence-agent/hooks/hooks.json +0 -49
  355. package/plugins/confluence-agent/hooks/reminder.mjs +0 -25
  356. package/plugins/confluence-agent/skills/confluence-agent/SKILL.md +0 -40
  357. package/plugins/create-connector/skills/create-connector/SKILL.md +0 -252
  358. package/plugins/db-agent/commands/db-agent.md +0 -6
  359. package/plugins/db-agent/hooks/db-guard.mjs +0 -110
  360. package/plugins/db-agent/hooks/hooks.json +0 -61
  361. package/plugins/db-agent/hooks/reminder.mjs +0 -16
  362. package/plugins/gcp-agent/commands/gcp-agent.md +0 -6
  363. package/plugins/gcp-agent/hooks/reminder.mjs +0 -16
  364. package/plugins/gcp-agent/package.json +0 -9
  365. package/plugins/github-agent/README.md +0 -13
  366. package/plugins/github-agent/commands/github-agent.md +0 -6
  367. package/plugins/github-agent/hooks/reminder.mjs +0 -16
  368. package/plugins/github-agent/skills/github-agent/SKILL.md +0 -41
  369. package/plugins/jira-agent/.claude-plugin/plugin.json +0 -6
  370. package/plugins/jira-agent/commands/jira-agent.md +0 -6
  371. package/plugins/jira-agent/hooks/reminder.mjs +0 -16
  372. package/plugins/jira-agent/skills/jira-agent/SKILL.md +0 -37
  373. package/plugins/notion-agent/.claude-plugin/plugin.json +0 -6
  374. package/plugins/notion-agent/commands/notion-agent.md +0 -6
  375. package/plugins/notion-agent/hooks/hooks.json +0 -49
  376. package/plugins/notion-agent/hooks/reminder.mjs +0 -17
  377. package/plugins/notion-agent/package.json +0 -8
  378. package/plugins/notion-agent/skills/notion-agent/SKILL.md +0 -48
  379. /package/plugins/{create-connector/skills/create-connector → connector-creator/skills/connector-creator}/assets/templates/bin.tmpl +0 -0
  380. /package/plugins/{create-connector/skills/create-connector → connector-creator/skills/connector-creator}/assets/templates/connector-SKILL.md.tmpl +0 -0
  381. /package/plugins/{create-connector/skills/create-connector → connector-creator/skills/connector-creator}/assets/templates/index.mjs.tmpl +0 -0
  382. /package/plugins/{create-connector/skills/create-connector → connector-creator/skills/connector-creator}/assets/templates/tests-example.mjs.tmpl +0 -0
  383. /package/plugins/{create-connector/skills/create-connector → connector-creator/skills/connector-creator}/references/action-design.md +0 -0
  384. /package/plugins/{create-connector/skills/create-connector → connector-creator/skills/connector-creator}/references/auth-patterns.md +0 -0
  385. /package/plugins/{create-connector/skills/create-connector → connector-creator/skills/connector-creator}/references/connector-anatomy.md +0 -0
  386. /package/plugins/{create-connector/skills/create-connector/references/db-agent-pointer.md → connector-creator/skills/connector-creator/references/db-connector-pointer.md} +0 -0
  387. /package/plugins/{create-connector/skills/create-connector → connector-creator/skills/connector-creator}/references/plugin-layer.md +0 -0
  388. /package/plugins/{create-connector/skills/create-connector → connector-creator/skills/connector-creator}/references/template-sync.md +0 -0
  389. /package/plugins/{create-connector/skills/create-connector → connector-creator/skills/connector-creator}/references/verification.md +0 -0
@@ -19,6 +19,9 @@ export function aggregateRecords(sessionId, connector, records) {
19
19
  let errors = 0;
20
20
  let start = records[0].ts;
21
21
  let end = records[0].ts;
22
+ let top1 = null;
23
+ let top2 = null;
24
+ let top3 = null;
22
25
  for (const rec of records) {
23
26
  totalBytes += rec.response_bytes;
24
27
  totalTokens += rec.estimated_tokens;
@@ -28,6 +31,20 @@ export function aggregateRecords(sessionId, connector, records) {
28
31
  start = rec.ts;
29
32
  if (rec.ts > end)
30
33
  end = rec.ts;
34
+ // ⚡ Bolt: Replace O(N log N) sort with O(N) Top-K manual tracking
35
+ // Avoids sorting the entire records array to find the 3 largest response_bytes.
36
+ if (!top1 || rec.response_bytes > top1.response_bytes) {
37
+ top3 = top2;
38
+ top2 = top1;
39
+ top1 = rec;
40
+ }
41
+ else if (!top2 || rec.response_bytes > top2.response_bytes) {
42
+ top3 = top2;
43
+ top2 = rec;
44
+ }
45
+ else if (!top3 || rec.response_bytes > top3.response_bytes) {
46
+ top3 = rec;
47
+ }
31
48
  const slot = byAction[rec.action] ??
32
49
  (byAction[rec.action] = {
33
50
  calls: 0,
@@ -53,9 +70,8 @@ export function aggregateRecords(sessionId, connector, records) {
53
70
  avg_ms: s.ms_count > 0 ? Math.round(s.ms_total / s.ms_count) : 0,
54
71
  };
55
72
  }
56
- const top_responses = [...records]
57
- .sort((a, b) => b.response_bytes - a.response_bytes)
58
- .slice(0, 3)
73
+ const top_responses = [top1, top2, top3]
74
+ .filter((r) => r !== null)
59
75
  .map((r) => ({ action: r.action, response_bytes: r.response_bytes }));
60
76
  return {
61
77
  session_id: sessionId,
@@ -1 +1 @@
1
- {"version":3,"file":"aggregate.js","sourceRoot":"","sources":["../../../src/toolkit/usage/aggregate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"aggregate.js","sourceRoot":"","sources":["../../../src/toolkit/usage/aggregate.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "narai-primitives",
3
- "version": "2.1.3",
3
+ "version": "2.2.0",
4
4
  "description": "Read-only connectors + planning hub + connector framework + credential resolution, in one package. Bundles what was @narai/connector-toolkit, @narai/connector-config, @narai/connector-hub, the seven @narai/<svc>-agent-connector packages, and @narai/credential-providers.",
5
5
  "type": "module",
6
6
  "main": "./dist/hub/index.js",
@@ -65,6 +65,14 @@
65
65
  "./notion": {
66
66
  "types": "./dist/connectors/notion/index.d.ts",
67
67
  "import": "./dist/connectors/notion/index.js"
68
+ },
69
+ "./linear": {
70
+ "types": "./dist/connectors/linear/index.d.ts",
71
+ "import": "./dist/connectors/linear/index.js"
72
+ },
73
+ "./gitlab": {
74
+ "types": "./dist/connectors/gitlab/index.d.ts",
75
+ "import": "./dist/connectors/gitlab/index.js"
68
76
  }
69
77
  },
70
78
  "bin": {
@@ -76,10 +84,12 @@
76
84
  "github-agent-connector": "./dist/connectors/github/cli.js",
77
85
  "jira-agent-connector": "./dist/connectors/jira/cli.js",
78
86
  "notion-agent-connector": "./dist/connectors/notion/cli.js",
87
+ "linear-agent-connector": "./dist/connectors/linear/cli.js",
88
+ "gitlab-agent-connector": "./dist/connectors/gitlab/cli.js",
79
89
  "usage-report": "./dist/toolkit/cli/usage-report.js"
80
90
  },
81
91
  "engines": {
82
- "node": ">=20.0.0"
92
+ "node": ">=20.10.0"
83
93
  },
84
94
  "files": [
85
95
  "dist/",
@@ -108,8 +118,10 @@
108
118
  },
109
119
  "dependencies": {
110
120
  "@anthropic-ai/claude-agent-sdk": "^0.2.119",
121
+ "adf-to-markdown": "^1.0.1",
111
122
  "better-sqlite3": "^12.9.0",
112
123
  "js-yaml": "^4.1.1",
124
+ "marklassian": "^1.2.1",
113
125
  "zod": "^3.23.0"
114
126
  },
115
127
  "optionalDependencies": {
@@ -0,0 +1,584 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Shared PreToolUse / PostToolUse / SessionStart / SessionEnd dispatcher
4
+ * for narai-primitives builtin Claude Code plugins.
5
+ *
6
+ * Usage:
7
+ * node dispatcher.mjs <event>
8
+ *
9
+ * Where <event> is one of: session-start, pre-tool-use, post-tool-use,
10
+ * session-end. Reads ${CLAUDE_PLUGIN_ROOT}/plugin-config.json for the
11
+ * plugin's identity and routes to the appropriate handler.
12
+ *
13
+ * Best-effort: handler-internal failures are logged to stderr but do not
14
+ * block tool execution. Argument / configuration errors exit with a
15
+ * non-zero code so Claude Code surfaces them to the operator.
16
+ */
17
+ import * as fs from "node:fs";
18
+ import * as path from "node:path";
19
+ import { fileURLToPath, pathToFileURL } from "node:url";
20
+ import { parsePluginConfig } from "./plugin-config.mjs";
21
+
22
+ const VALID_EVENTS = new Set([
23
+ "session-start",
24
+ "pre-tool-use",
25
+ "post-tool-use",
26
+ "session-end",
27
+ ]);
28
+
29
+ // Only run main() when invoked as a CLI, not when imported by tests.
30
+ // Resolve symlinks on both sides so the smart-bootstrap dedup path
31
+ // (where `node_modules/narai-primitives` is symlinked from a sibling
32
+ // plugin) still recognizes itself as the CLI entrypoint.
33
+ const isMainScript = (() => {
34
+ if (process.argv[1] === undefined) return false;
35
+ try {
36
+ const realArgv = fs.realpathSync(process.argv[1]);
37
+ const realSelf = fs.realpathSync(fileURLToPath(import.meta.url));
38
+ return realArgv === realSelf;
39
+ } catch {
40
+ // Fall back to literal comparison if realpath can't resolve.
41
+ return process.argv[1] === fileURLToPath(import.meta.url);
42
+ }
43
+ })();
44
+
45
+ if (isMainScript) {
46
+ main().catch((err) => {
47
+ process.stderr.write(`dispatcher: ${err?.message ?? err}\n`);
48
+ process.exit(1);
49
+ });
50
+ }
51
+
52
+ async function main() {
53
+ const event = process.argv[2];
54
+ if (!VALID_EVENTS.has(event)) {
55
+ process.stderr.write(
56
+ `dispatcher: unknown event '${event}' (expected one of ${[...VALID_EVENTS].join(", ")})\n`,
57
+ );
58
+ process.exit(2);
59
+ }
60
+
61
+ const root = process.env.CLAUDE_PLUGIN_ROOT;
62
+ if (!root) {
63
+ process.stderr.write("dispatcher: CLAUDE_PLUGIN_ROOT not set\n");
64
+ process.exit(2);
65
+ }
66
+
67
+ const cfgPath = path.join(root, "plugin-config.json");
68
+ if (!fs.existsSync(cfgPath)) {
69
+ process.stderr.write(`dispatcher: missing ${cfgPath}\n`);
70
+ process.exit(2);
71
+ }
72
+ const cfg = parsePluginConfig(fs.readFileSync(cfgPath, "utf-8"));
73
+
74
+ switch (event) {
75
+ case "session-start":
76
+ await onSessionStart(cfg);
77
+ break;
78
+ case "pre-tool-use":
79
+ await onPreToolUse(cfg);
80
+ break;
81
+ case "post-tool-use":
82
+ await onPostToolUse(cfg);
83
+ break;
84
+ case "session-end":
85
+ await onSessionEnd(cfg);
86
+ break;
87
+ }
88
+ process.exit(0);
89
+ }
90
+
91
+ async function loadToolkit() {
92
+ const { existsSync } = fs;
93
+ const { homedir } = await import("node:os");
94
+ const { fileURLToPath, pathToFileURL } = await import("node:url");
95
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
96
+ const candidates = [
97
+ // 1. Bundled: dispatcher at narai-primitives/plugin-hooks/; toolkit at narai-primitives/dist/toolkit/guardrail.js
98
+ path.join(__dirname, "..", "dist", "toolkit", "guardrail.js"),
99
+ // 2. Claude Code plugin install
100
+ process.env.CLAUDE_PLUGIN_DATA
101
+ ? path.join(process.env.CLAUDE_PLUGIN_DATA, "node_modules", "narai-primitives", "dist", "toolkit", "guardrail.js")
102
+ : null,
103
+ ].filter((p) => p !== null);
104
+ for (const p of candidates) {
105
+ if (!existsSync(p)) continue;
106
+ try {
107
+ return await import(pathToFileURL(p).href);
108
+ } catch {
109
+ // try next
110
+ }
111
+ }
112
+ return null;
113
+ }
114
+
115
+ /**
116
+ * Lazily load the db audit module from dist. Returns the module namespace
117
+ * ({ enableAudit, logEvent, scrubSqlSecrets, ... }) or null if unavailable.
118
+ * Only used when NARAI_AUDIT_PATH is set, so the common path stays cheap.
119
+ */
120
+ async function loadAudit() {
121
+ const { existsSync } = fs;
122
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
123
+ const candidates = [
124
+ path.join(__dirname, "..", "dist", "connectors", "db", "lib", "audit.js"),
125
+ process.env.CLAUDE_PLUGIN_DATA
126
+ ? path.join(process.env.CLAUDE_PLUGIN_DATA, "node_modules", "narai-primitives", "dist", "connectors", "db", "lib", "audit.js")
127
+ : null,
128
+ ].filter((p) => p !== null);
129
+ for (const p of candidates) {
130
+ if (!existsSync(p)) continue;
131
+ try {
132
+ return await import(pathToFileURL(p).href);
133
+ } catch {
134
+ // try next
135
+ }
136
+ }
137
+ return null;
138
+ }
139
+
140
+ /**
141
+ * Walk siblings of `pluginDataDir` looking for a `node_modules/narai-primitives`
142
+ * at `wantedVersion`. Returns the matched node_modules path, or null if no
143
+ * usable sibling found. Used to skip redundant npm install when N builtin
144
+ * plugins are loaded in the same Claude Code session.
145
+ */
146
+ export function findSiblingInstall(pluginDataDir, wantedVersion) {
147
+ const parent = path.dirname(pluginDataDir);
148
+ let entries;
149
+ try {
150
+ entries = fs.readdirSync(parent, { withFileTypes: true });
151
+ } catch {
152
+ return null;
153
+ }
154
+ for (const entry of entries) {
155
+ if (!entry.isDirectory()) continue;
156
+ const candidate = path.join(parent, entry.name);
157
+ if (candidate === pluginDataDir) continue;
158
+ const pkgJson = path.join(
159
+ candidate,
160
+ "node_modules",
161
+ "narai-primitives",
162
+ "package.json",
163
+ );
164
+ if (!fs.existsSync(pkgJson)) continue;
165
+ try {
166
+ const meta = JSON.parse(fs.readFileSync(pkgJson, "utf-8"));
167
+ if (meta.version === wantedVersion) {
168
+ return path.join(candidate, "node_modules");
169
+ }
170
+ } catch {
171
+ continue;
172
+ }
173
+ }
174
+ return null;
175
+ }
176
+
177
+ async function onSessionStart(cfg) {
178
+ const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT;
179
+ const pluginData = process.env.CLAUDE_PLUGIN_DATA;
180
+ if (!pluginRoot || !pluginData) return;
181
+
182
+ await ensureBootstrap(pluginRoot, pluginData);
183
+
184
+ // Best-effort: emit nudge banner if the toolkit is reachable.
185
+ try {
186
+ const reminderPath = path.join(
187
+ pluginData,
188
+ "node_modules",
189
+ "narai-primitives",
190
+ "dist",
191
+ "toolkit",
192
+ "plugin",
193
+ "reminder.js",
194
+ );
195
+ if (fs.existsSync(reminderPath)) {
196
+ // pathToFileURL is required on Windows — Node refuses raw absolute
197
+ // paths as ESM specifiers (ERR_UNSUPPORTED_ESM_URL_SCHEME).
198
+ const mod = await import(pathToFileURL(reminderPath).href);
199
+ const decision = mod.evaluateNudge({ connectors: [cfg.name] });
200
+ if (decision.nudge) process.stdout.write(decision.banner + "\n");
201
+ }
202
+ } catch (err) {
203
+ process.stderr.write(`dispatcher: nudge failed (${err.message})\n`);
204
+ }
205
+
206
+ // Best-effort: stale-summarize.
207
+ try {
208
+ const stalePath = path.join(
209
+ pluginData,
210
+ "node_modules",
211
+ "narai-primitives",
212
+ "plugin-hooks",
213
+ "stale-summarize.mjs",
214
+ );
215
+ if (fs.existsSync(stalePath)) {
216
+ process.env.USAGE_CONNECTOR_NAME = cfg.name;
217
+ await import(pathToFileURL(stalePath).href);
218
+ }
219
+ } catch (err) {
220
+ process.stderr.write(`dispatcher: stale-summarize failed (${err.message})\n`);
221
+ }
222
+ }
223
+
224
+ async function onPreToolUse(cfg) {
225
+ const stdin = await readStdin();
226
+ if (!stdin) return;
227
+ let payload;
228
+ try {
229
+ payload = JSON.parse(stdin);
230
+ } catch {
231
+ return;
232
+ }
233
+ // Derive the tool being gated and the text to scan. Bash scans the
234
+ // command; Write scans the file content; Edit scans the incoming text
235
+ // (new_string only — old_string is the text being removed). `command`
236
+ // therefore holds the candidate text for whichever tool fired.
237
+ let scanTool;
238
+ let command;
239
+ if (payload.tool_name === "Bash") {
240
+ scanTool = "Bash";
241
+ command = payload.tool_input?.command;
242
+ } else if (payload.tool_name === "Write") {
243
+ scanTool = "Write";
244
+ command = payload.tool_input?.content;
245
+ } else if (payload.tool_name === "Edit") {
246
+ scanTool = "Edit";
247
+ command = payload.tool_input?.new_string;
248
+ } else {
249
+ return;
250
+ }
251
+ if (typeof command !== "string" || command.length === 0) return;
252
+
253
+ const decisions = [];
254
+
255
+ // 1. db-guard (Bash only; only if kind=db, and not opted out via user_config).
256
+ // The token-blocklist engine is command-shaped and meaningless for file content.
257
+ if (scanTool === "Bash" && cfg.kind === "db" && process.env.DB_AGENT_GUARDRAILS !== "off") {
258
+ const guardrailsPath = path.join(
259
+ process.env.CLAUDE_PLUGIN_ROOT,
260
+ "hooks",
261
+ "guardrails.json",
262
+ );
263
+ if (fs.existsSync(guardrailsPath)) {
264
+ try {
265
+ const toolkit = await loadToolkit();
266
+ if (toolkit && typeof toolkit.findBlockingRule === "function") {
267
+ const { findBlockingRule, defaultDenyMessage, loadGuardrailManifest } = toolkit;
268
+ const manifest = loadGuardrailManifest(guardrailsPath);
269
+ const match = findBlockingRule(command, [manifest]);
270
+ if (match) {
271
+ decisions.push({
272
+ decision: "deny",
273
+ reason: defaultDenyMessage(match),
274
+ });
275
+ }
276
+ } else if (effectiveEnforcement(undefined) === "fail_closed") {
277
+ decisions.push({
278
+ decision: "deny",
279
+ reason: "fail-closed enforcement: db guardrail engine is unavailable",
280
+ });
281
+ }
282
+ } catch (err) {
283
+ process.stderr.write(`dispatcher: db-guard failed (${err.message})\n`);
284
+ if (effectiveEnforcement(undefined) === "fail_closed") {
285
+ decisions.push({
286
+ decision: "deny",
287
+ reason: `fail-closed enforcement: db guardrail manifest could not be evaluated (${err.message})`,
288
+ });
289
+ }
290
+ }
291
+ }
292
+ }
293
+
294
+ // 2. user-connector gates from $HOME and cwd. Mirror connector-gate.mjs:
295
+ // honor NARAI_GATE_DISABLE (comma-separated rule names) so operators
296
+ // can silence a noisy rule without editing gates.json.
297
+ const disabled = new Set(
298
+ (process.env.NARAI_GATE_DISABLE ?? "")
299
+ .split(",")
300
+ .map((s) => s.trim())
301
+ .filter(Boolean),
302
+ );
303
+ // 3. plugin-shipped gates.json at CLAUDE_PLUGIN_ROOT/gates.json — lets
304
+ // hook-only plugins (e.g. git-connector) ship default rules out-of-the-box.
305
+ const pluginGatesFile = path.join(process.env.CLAUDE_PLUGIN_ROOT, "gates.json");
306
+ if (fs.existsSync(pluginGatesFile)) {
307
+ try {
308
+ const gateCfg = JSON.parse(fs.readFileSync(pluginGatesFile, "utf-8"));
309
+ applyGatesManifest(gateCfg, cfg.name, command, disabled, decisions, scanTool);
310
+ } catch (err) {
311
+ process.stderr.write(
312
+ `dispatcher: plugin-root gate scan failed (${err.message})\n`,
313
+ );
314
+ if (effectiveEnforcement(undefined) === "fail_closed") {
315
+ decisions.push({
316
+ decision: "deny",
317
+ reason: `fail-closed enforcement: gates manifest at ${pluginGatesFile} could not be parsed`,
318
+ });
319
+ }
320
+ }
321
+ }
322
+
323
+ // 4. user-connector gates from $HOME and cwd.
324
+ const home = process.env.HOME ?? "";
325
+ const cwd = process.cwd();
326
+ for (const root of [home, cwd]) {
327
+ if (!root) continue;
328
+ const gatesDir = path.join(root, ".connectors", "connectors");
329
+ if (!fs.existsSync(gatesDir)) continue;
330
+ let slugs;
331
+ try {
332
+ slugs = fs
333
+ .readdirSync(gatesDir, { withFileTypes: true })
334
+ .filter((e) => e.isDirectory())
335
+ .map((e) => e.name);
336
+ } catch {
337
+ continue;
338
+ }
339
+ for (const slug of slugs) {
340
+ const gatesFile = path.join(gatesDir, slug, "gates.json");
341
+ if (!fs.existsSync(gatesFile)) continue;
342
+ try {
343
+ const gateCfg = JSON.parse(fs.readFileSync(gatesFile, "utf-8"));
344
+ applyGatesManifest(gateCfg, slug, command, disabled, decisions, scanTool);
345
+ } catch (err) {
346
+ process.stderr.write(
347
+ `dispatcher: gate scan failed for ${gatesFile} (${err.message})\n`,
348
+ );
349
+ if (effectiveEnforcement(undefined) === "fail_closed") {
350
+ decisions.push({
351
+ decision: "deny",
352
+ reason: `fail-closed enforcement: gates manifest at ${gatesFile} could not be parsed`,
353
+ });
354
+ }
355
+ }
356
+ }
357
+ }
358
+
359
+ if (decisions.length === 0) return;
360
+ const rank = { deny: 2, ask: 1, allow: 0 };
361
+ decisions.sort((a, b) => rank[b.decision] - rank[a.decision]);
362
+ const winner = decisions[0];
363
+ process.stdout.write(JSON.stringify({
364
+ hookSpecificOutput: {
365
+ hookEventName: "PreToolUse",
366
+ permissionDecision: winner.decision,
367
+ permissionDecisionReason: winner.reason,
368
+ },
369
+ }));
370
+
371
+ // Best-effort audit of blocked/escalated decisions. Only runs when an
372
+ // audit destination is configured, keeping the common allow path cheap.
373
+ const auditPath = process.env.NARAI_AUDIT_PATH;
374
+ if (auditPath && (winner.decision === "deny" || winner.decision === "ask")) {
375
+ try {
376
+ const audit = await loadAudit();
377
+ if (audit && typeof audit.logEvent === "function") {
378
+ audit.enableAudit(auditPath);
379
+ const scrub = typeof audit.scrubSqlSecrets === "function"
380
+ ? audit.scrubSqlSecrets
381
+ : (s) => s;
382
+ audit.logEvent({
383
+ event_type: winner.decision === "deny" ? "guardrail_deny" : "guardrail_ask",
384
+ details: { tool: payload.tool_name, command: scrub(command), reason: winner.reason },
385
+ });
386
+ }
387
+ } catch (err) {
388
+ process.stderr.write(`dispatcher: decision audit failed (${err.message})\n`);
389
+ }
390
+ }
391
+ }
392
+
393
+ async function readStdin() {
394
+ const chunks = [];
395
+ for await (const chunk of process.stdin) chunks.push(chunk);
396
+ return Buffer.concat(chunks).toString("utf-8").trim();
397
+ }
398
+ async function onPostToolUse(cfg) {
399
+ const pluginData = process.env.CLAUDE_PLUGIN_DATA;
400
+ if (!pluginData) return;
401
+ const usagePath = path.join(
402
+ pluginData,
403
+ "node_modules",
404
+ "narai-primitives",
405
+ "plugin-hooks",
406
+ "usage-record.mjs",
407
+ );
408
+ if (!fs.existsSync(usagePath)) return;
409
+ process.env.USAGE_CONNECTOR_NAME = cfg.name;
410
+ if (cfg.binPath) process.env.USAGE_BIN_HINT = cfg.binPath;
411
+ try {
412
+ await import(pathToFileURL(usagePath).href);
413
+ } catch (err) {
414
+ process.stderr.write(`dispatcher: usage-record failed (${err.message})\n`);
415
+ }
416
+ }
417
+ async function onSessionEnd(cfg) {
418
+ const pluginData = process.env.CLAUDE_PLUGIN_DATA;
419
+ if (!pluginData) return;
420
+ const summaryPath = path.join(
421
+ pluginData,
422
+ "node_modules",
423
+ "narai-primitives",
424
+ "plugin-hooks",
425
+ "session-summary.mjs",
426
+ );
427
+ if (!fs.existsSync(summaryPath)) return;
428
+ // session-summary.mjs only runs its `main()` when it's the CLI entry
429
+ // point (`import.meta.url === file://${process.argv[1]}`). Importing it
430
+ // here would be a no-op; spawn it as a subprocess so the guard passes.
431
+ try {
432
+ const { spawnSync } = await import("node:child_process");
433
+ spawnSync("node", [summaryPath], {
434
+ stdio: "inherit",
435
+ env: { ...process.env, USAGE_CONNECTOR_NAME: cfg.name },
436
+ });
437
+ } catch (err) {
438
+ process.stderr.write(`dispatcher: session-summary failed (${err.message})\n`);
439
+ }
440
+ }
441
+
442
+ /**
443
+ * Ensure narai-primitives is installed in pluginData. Tries (in order):
444
+ * 1. Skip if already installed at the right version.
445
+ * 2. Symlink from a sibling plugin's node_modules.
446
+ * 3. npm install in pluginData.
447
+ *
448
+ * Best-effort: all branches return without throwing. The caller proceeds
449
+ * to side effects (nudge, stale-summarize, etc.) even when the install
450
+ * is cached, so recurring per-session behavior fires every run.
451
+ */
452
+ async function ensureBootstrap(pluginRoot, pluginData) {
453
+ const rootPkg = path.join(pluginRoot, "package.json");
454
+ if (!fs.existsSync(rootPkg)) return;
455
+ let rootMeta;
456
+ try {
457
+ rootMeta = JSON.parse(fs.readFileSync(rootPkg, "utf-8"));
458
+ } catch {
459
+ return;
460
+ }
461
+ // Read the wanted narai-primitives version from the plugin's
462
+ // `dependencies` block (e.g. `"^2.1.3"`) and strip the semver
463
+ // prefix so the equality check matches the installed package's
464
+ // resolved version field (e.g. `"2.1.3"`). The plugin's own
465
+ // `version` is independent and not interchangeable.
466
+ const depRange = rootMeta.dependencies?.["narai-primitives"];
467
+ const wantVersion = depRange?.replace(/^[\^~>=< ]+/, "");
468
+ if (!wantVersion) return;
469
+
470
+ fs.mkdirSync(pluginData, { recursive: true });
471
+
472
+ const myInstall = path.join(pluginData, "node_modules", "narai-primitives");
473
+ if (fs.existsSync(myInstall)) {
474
+ try {
475
+ const installed = JSON.parse(
476
+ fs.readFileSync(path.join(myInstall, "package.json"), "utf-8"),
477
+ );
478
+ if (installed.version === wantVersion) return;
479
+ } catch {
480
+ // Fall through to re-install.
481
+ }
482
+ }
483
+
484
+ const sibling = findSiblingInstall(pluginData, wantVersion);
485
+ if (sibling !== null) {
486
+ try {
487
+ const myNodeModules = path.join(pluginData, "node_modules");
488
+ if (fs.existsSync(myNodeModules)) {
489
+ fs.rmSync(myNodeModules, { recursive: true, force: true });
490
+ }
491
+ fs.symlinkSync(sibling, myNodeModules, "dir");
492
+ return;
493
+ } catch {
494
+ // Fall through to install.
495
+ }
496
+ }
497
+
498
+ fs.copyFileSync(rootPkg, path.join(pluginData, "package.json"));
499
+ const { spawnSync } = await import("node:child_process");
500
+ spawnSync("npm", ["install", "--no-audit", "--no-fund"], {
501
+ cwd: pluginData,
502
+ stdio: "inherit",
503
+ });
504
+ }
505
+
506
+ /**
507
+ * Resolve the effective enforcement posture from the global
508
+ * NARAI_GATE_ENFORCEMENT env var and an optional manifest-level field.
509
+ * Strictest wins: fail-closed if either requests it, else fail-open.
510
+ */
511
+ export function effectiveEnforcement(manifestEnforcement) {
512
+ const env = process.env.NARAI_GATE_ENFORCEMENT;
513
+ if (env === "fail_closed" || manifestEnforcement === "fail_closed") {
514
+ return "fail_closed";
515
+ }
516
+ return "fail_open";
517
+ }
518
+
519
+ /**
520
+ * Apply a parsed gates.json manifest to a command. Rules with invalid
521
+ * shape, disabled names, or uncompilable patterns are skipped. Anchored
522
+ * patterns match per-segment so chaining (`echo ok; psql ...`) can't bypass.
523
+ *
524
+ * Under fail-closed enforcement (env var or the manifest's `enforcement`
525
+ * field), a rule whose pattern will not compile becomes a hard deny instead
526
+ * of being silently skipped — we cannot prove the command is safe.
527
+ */
528
+ export function applyGatesManifest(manifest, source, text, disabled, decisions, scanTool = "Bash") {
529
+ const enforcement = effectiveEnforcement(manifest.enforcement);
530
+ // Bash commands are split on chaining operators so anchored rules apply
531
+ // per-segment. File content (Write/Edit) is matched as a single unit so
532
+ // characters like `;` or `|` inside the file do not fragment it.
533
+ const segments = scanTool === "Bash" ? splitCompound(text) : [text];
534
+ for (const rule of manifest.rules ?? []) {
535
+ if (
536
+ !["deny", "ask", "allow"].includes(rule.decision) ||
537
+ typeof rule.pattern !== "string"
538
+ ) continue;
539
+ if (typeof rule.name === "string" && disabled.has(rule.name)) continue;
540
+ // A rule applies to a tool only if listed in `applies_to`. Default is
541
+ // Bash-only, so every existing rule keeps its current behavior and is
542
+ // skipped on Write/Edit unless it explicitly opts in.
543
+ const appliesTo = Array.isArray(rule.applies_to) ? rule.applies_to : ["Bash"];
544
+ if (!appliesTo.includes(scanTool)) continue;
545
+ let re;
546
+ try { re = new RegExp(rule.pattern); } catch {
547
+ if (enforcement === "fail_closed") {
548
+ decisions.push({
549
+ decision: "deny",
550
+ reason: `fail-closed enforcement: ${source} gate rule '${rule.name ?? "rule"}' has an invalid pattern`,
551
+ });
552
+ }
553
+ continue;
554
+ }
555
+ for (const segment of segments) {
556
+ if (re.test(segment)) {
557
+ decisions.push({
558
+ decision: rule.decision,
559
+ reason: rule.reason ?? `${source} gate: ${rule.name ?? "rule"}`,
560
+ });
561
+ break;
562
+ }
563
+ }
564
+ }
565
+ }
566
+
567
+ /**
568
+ * Split a bash command on chaining operators so anchored gate rules
569
+ * apply per-segment. Mirrors connector-gate.mjs's behavior.
570
+ */
571
+ function splitCompound(cmd) {
572
+ const parts = cmd.split(/\s*(?:&&|\|\||;|\|)\s*/);
573
+ return parts
574
+ .map((p) => stripPrefix(p.trim()))
575
+ .filter((p) => p.length > 0);
576
+ }
577
+
578
+ function stripPrefix(s) {
579
+ let cur = s;
580
+ while (/^[A-Za-z_][A-Za-z0-9_]*=\S*\s+/.test(cur)) {
581
+ cur = cur.replace(/^[A-Za-z_][A-Za-z0-9_]*=\S*\s+/, "");
582
+ }
583
+ return cur.replace(/^(sudo|nice|time)\s+/, "");
584
+ }