@probelabs/visor 0.1.107 โ†’ 0.1.112

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 (235) hide show
  1. package/README.md +6 -0
  2. package/defaults/task-refinement.yaml +7 -3
  3. package/defaults/visor.tests.yaml +13 -2
  4. package/defaults/visor.yaml +1 -0
  5. package/dist/663.index.js +3 -2
  6. package/dist/80.index.js +3 -2
  7. package/dist/ai-review-service.d.ts +13 -9
  8. package/dist/ai-review-service.d.ts.map +1 -1
  9. package/dist/cli-main.d.ts.map +1 -1
  10. package/dist/cli.d.ts.map +1 -1
  11. package/dist/config.d.ts.map +1 -1
  12. package/dist/debug-visualizer/ws-server.d.ts +7 -1
  13. package/dist/debug-visualizer/ws-server.d.ts.map +1 -1
  14. package/dist/defaults/task-refinement.yaml +7 -3
  15. package/dist/defaults/visor.tests.yaml +13 -2
  16. package/dist/defaults/visor.yaml +1 -0
  17. package/dist/docs/advanced-ai.md +60 -1
  18. package/dist/docs/ai-configuration.md +67 -0
  19. package/dist/docs/ai-custom-tools-usage.md +261 -0
  20. package/dist/docs/ai-custom-tools.md +392 -0
  21. package/dist/docs/bot-transports-rfc.md +23 -0
  22. package/dist/docs/configuration.md +21 -0
  23. package/dist/docs/engine-pause-resume-rfc.md +192 -0
  24. package/dist/docs/lifecycle-hooks.md +253 -0
  25. package/dist/docs/liquid-templates.md +143 -0
  26. package/dist/docs/providers/git-checkout.md +589 -0
  27. package/dist/docs/recipes.md +458 -5
  28. package/dist/docs/rfc/git-checkout-step.md +601 -0
  29. package/dist/docs/rfc/on_init-hook.md +1294 -0
  30. package/dist/docs/rfc/workspace-isolation.md +216 -0
  31. package/dist/docs/router-patterns.md +339 -0
  32. package/dist/event-bus/types.d.ts +14 -0
  33. package/dist/event-bus/types.d.ts.map +1 -1
  34. package/dist/examples/ai-custom-tools-example.yaml +206 -0
  35. package/dist/examples/ai-custom-tools-simple.yaml +76 -0
  36. package/dist/examples/git-checkout-basic.yaml +32 -0
  37. package/dist/examples/git-checkout-compare.yaml +59 -0
  38. package/dist/examples/git-checkout-cross-repo.yaml +76 -0
  39. package/dist/examples/on-init-import-demo.yaml +179 -0
  40. package/dist/examples/reusable-tools.yaml +92 -0
  41. package/dist/examples/reusable-workflows.yaml +88 -0
  42. package/dist/examples/session-reuse-self.yaml +81 -0
  43. package/dist/examples/slack-simple-chat.yaml +775 -0
  44. package/dist/failure-condition-evaluator.d.ts +2 -0
  45. package/dist/failure-condition-evaluator.d.ts.map +1 -1
  46. package/dist/frontends/github-frontend.d.ts +20 -0
  47. package/dist/frontends/github-frontend.d.ts.map +1 -1
  48. package/dist/frontends/host.d.ts +4 -0
  49. package/dist/frontends/host.d.ts.map +1 -1
  50. package/dist/frontends/slack-frontend.d.ts +58 -0
  51. package/dist/frontends/slack-frontend.d.ts.map +1 -0
  52. package/dist/generated/config-schema.d.ts +409 -41
  53. package/dist/generated/config-schema.d.ts.map +1 -1
  54. package/dist/generated/config-schema.json +436 -47
  55. package/dist/github-comments.d.ts +2 -0
  56. package/dist/github-comments.d.ts.map +1 -1
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +83587 -56085
  59. package/dist/liquid-extensions.d.ts.map +1 -1
  60. package/dist/logger.d.ts +1 -0
  61. package/dist/logger.d.ts.map +1 -1
  62. package/dist/output/traces/{run-2025-11-21T11-50-46-505Z.ndjson โ†’ run-2026-01-21T05-37-24-446Z.ndjson} +91 -91
  63. package/dist/output/traces/run-2026-01-21T05-38-18-580Z.ndjson +1067 -0
  64. package/dist/output-formatters.d.ts.map +1 -1
  65. package/dist/providers/ai-check-provider.d.ts +12 -0
  66. package/dist/providers/ai-check-provider.d.ts.map +1 -1
  67. package/dist/providers/check-provider-registry.d.ts.map +1 -1
  68. package/dist/providers/check-provider.interface.d.ts +9 -0
  69. package/dist/providers/check-provider.interface.d.ts.map +1 -1
  70. package/dist/providers/command-check-provider.d.ts.map +1 -1
  71. package/dist/providers/custom-tool-executor.d.ts.map +1 -1
  72. package/dist/providers/git-checkout-provider.d.ts +25 -0
  73. package/dist/providers/git-checkout-provider.d.ts.map +1 -0
  74. package/dist/providers/http-client-provider.d.ts +3 -0
  75. package/dist/providers/http-client-provider.d.ts.map +1 -1
  76. package/dist/providers/human-input-check-provider.d.ts +2 -0
  77. package/dist/providers/human-input-check-provider.d.ts.map +1 -1
  78. package/dist/providers/log-check-provider.d.ts.map +1 -1
  79. package/dist/providers/mcp-check-provider.d.ts +1 -1
  80. package/dist/providers/mcp-check-provider.d.ts.map +1 -1
  81. package/dist/providers/mcp-custom-sse-server.d.ts +66 -0
  82. package/dist/providers/mcp-custom-sse-server.d.ts.map +1 -0
  83. package/dist/providers/memory-check-provider.d.ts.map +1 -1
  84. package/dist/providers/script-check-provider.d.ts.map +1 -1
  85. package/dist/providers/workflow-check-provider.d.ts.map +1 -1
  86. package/dist/reviewer.d.ts.map +1 -1
  87. package/dist/sdk/check-provider-registry-534KL5HT.mjs +27 -0
  88. package/dist/sdk/chunk-23L3QRYX.mjs +16872 -0
  89. package/dist/sdk/chunk-23L3QRYX.mjs.map +1 -0
  90. package/dist/sdk/{chunk-OOZITMRU.mjs โ†’ chunk-3OMWVM6J.mjs} +11 -1
  91. package/dist/sdk/{chunk-OOZITMRU.mjs.map โ†’ chunk-3OMWVM6J.mjs.map} +1 -1
  92. package/dist/sdk/{chunk-37ZSCMFC.mjs โ†’ chunk-7UK3NIIT.mjs} +2 -2
  93. package/dist/sdk/{chunk-VMPLF6FT.mjs โ†’ chunk-AGIZJ4UZ.mjs} +50 -4
  94. package/dist/sdk/chunk-AGIZJ4UZ.mjs.map +1 -0
  95. package/dist/sdk/{chunk-IEO6CFLG.mjs โ†’ chunk-AIVFBIS4.mjs} +161 -5
  96. package/dist/sdk/chunk-AIVFBIS4.mjs.map +1 -0
  97. package/dist/sdk/chunk-AK6BVWIT.mjs +426 -0
  98. package/dist/sdk/chunk-AK6BVWIT.mjs.map +1 -0
  99. package/dist/sdk/chunk-AUT26LHW.mjs +139 -0
  100. package/dist/sdk/chunk-AUT26LHW.mjs.map +1 -0
  101. package/dist/sdk/chunk-BOVFH3LI.mjs +232 -0
  102. package/dist/sdk/chunk-BOVFH3LI.mjs.map +1 -0
  103. package/dist/sdk/chunk-HTOKWMPO.mjs +157 -0
  104. package/dist/sdk/chunk-HTOKWMPO.mjs.map +1 -0
  105. package/dist/sdk/{chunk-6Y4YTKCF.mjs โ†’ chunk-NAW3DB3I.mjs} +2 -2
  106. package/dist/sdk/{chunk-OWUVOILT.mjs โ†’ chunk-QR7MOMJH.mjs} +4 -3
  107. package/dist/sdk/{chunk-OWUVOILT.mjs.map โ†’ chunk-QR7MOMJH.mjs.map} +1 -1
  108. package/dist/sdk/{chunk-PTL3K3PN.mjs โ†’ chunk-QY2XYPEV.mjs} +488 -60
  109. package/dist/sdk/chunk-QY2XYPEV.mjs.map +1 -0
  110. package/dist/sdk/{chunk-OZJ263FM.mjs โ†’ chunk-SIWNBRTK.mjs} +29 -215
  111. package/dist/sdk/chunk-SIWNBRTK.mjs.map +1 -0
  112. package/dist/sdk/command-executor-TYUV6HUS.mjs +14 -0
  113. package/dist/sdk/{config-M4ZNO6NU.mjs โ†’ config-YNC2EOOT.mjs} +5 -3
  114. package/dist/sdk/{failure-condition-evaluator-NBO5YRXW.mjs โ†’ failure-condition-evaluator-YGTF2GHG.mjs} +6 -5
  115. package/dist/sdk/{github-frontend-4AWRJT7D.mjs โ†’ github-frontend-SIAEOCON.mjs} +190 -12
  116. package/dist/sdk/github-frontend-SIAEOCON.mjs.map +1 -0
  117. package/dist/sdk/{host-7GBC3S7L.mjs โ†’ host-DXUYTNMU.mjs} +5 -2
  118. package/dist/sdk/host-DXUYTNMU.mjs.map +1 -0
  119. package/dist/sdk/{liquid-extensions-C7EG3YKH.mjs โ†’ liquid-extensions-PKWCKK7E.mjs} +5 -4
  120. package/dist/sdk/memory-store-XGBB7LX7.mjs +12 -0
  121. package/dist/sdk/prompt-state-YRJY6QAL.mjs +16 -0
  122. package/dist/sdk/{renderer-schema-6RF26VUS.mjs โ†’ renderer-schema-LPKN5UJS.mjs} +3 -2
  123. package/dist/sdk/{renderer-schema-6RF26VUS.mjs.map โ†’ renderer-schema-LPKN5UJS.mjs.map} +1 -1
  124. package/dist/sdk/{routing-RP56JTV2.mjs โ†’ routing-6N45MJ4F.mjs} +7 -6
  125. package/dist/sdk/sdk.d.mts +219 -5
  126. package/dist/sdk/sdk.d.ts +219 -5
  127. package/dist/sdk/sdk.js +21329 -14908
  128. package/dist/sdk/sdk.js.map +1 -1
  129. package/dist/sdk/sdk.mjs +407 -12874
  130. package/dist/sdk/sdk.mjs.map +1 -1
  131. package/dist/sdk/{session-registry-N5FFYFTM.mjs โ†’ session-registry-4E6YRQ77.mjs} +2 -2
  132. package/dist/sdk/session-registry-4E6YRQ77.mjs.map +1 -0
  133. package/dist/sdk/slack-frontend-BVKW3GD5.mjs +735 -0
  134. package/dist/sdk/slack-frontend-BVKW3GD5.mjs.map +1 -0
  135. package/dist/sdk/{tracer-init-WP4X46IF.mjs โ†’ tracer-init-GSLPPLCD.mjs} +2 -2
  136. package/dist/sdk/tracer-init-GSLPPLCD.mjs.map +1 -0
  137. package/dist/sdk/workflow-registry-R6KSACFR.mjs +12 -0
  138. package/dist/sdk/workflow-registry-R6KSACFR.mjs.map +1 -0
  139. package/dist/slack/adapter.d.ts +36 -0
  140. package/dist/slack/adapter.d.ts.map +1 -0
  141. package/dist/slack/cache-prewarmer.d.ts +31 -0
  142. package/dist/slack/cache-prewarmer.d.ts.map +1 -0
  143. package/dist/slack/client.d.ts +77 -0
  144. package/dist/slack/client.d.ts.map +1 -0
  145. package/dist/slack/markdown.d.ts +45 -0
  146. package/dist/slack/markdown.d.ts.map +1 -0
  147. package/dist/slack/prompt-state.d.ts +33 -0
  148. package/dist/slack/prompt-state.d.ts.map +1 -0
  149. package/dist/slack/rate-limiter.d.ts +56 -0
  150. package/dist/slack/rate-limiter.d.ts.map +1 -0
  151. package/dist/slack/signature.d.ts +2 -0
  152. package/dist/slack/signature.d.ts.map +1 -0
  153. package/dist/slack/socket-runner.d.ts +42 -0
  154. package/dist/slack/socket-runner.d.ts.map +1 -0
  155. package/dist/slack/thread-cache.d.ts +51 -0
  156. package/dist/slack/thread-cache.d.ts.map +1 -0
  157. package/dist/state-machine/context/build-engine-context.d.ts +8 -0
  158. package/dist/state-machine/context/build-engine-context.d.ts.map +1 -1
  159. package/dist/state-machine/dispatch/execution-invoker.d.ts.map +1 -1
  160. package/dist/state-machine/dispatch/foreach-processor.d.ts.map +1 -1
  161. package/dist/state-machine/dispatch/on-init-handlers.d.ts +43 -0
  162. package/dist/state-machine/dispatch/on-init-handlers.d.ts.map +1 -0
  163. package/dist/state-machine/dispatch/stats-manager.d.ts.map +1 -1
  164. package/dist/state-machine/dispatch/template-renderer.d.ts.map +1 -1
  165. package/dist/state-machine/runner.d.ts +6 -0
  166. package/dist/state-machine/runner.d.ts.map +1 -1
  167. package/dist/state-machine/states/level-dispatch.d.ts.map +1 -1
  168. package/dist/state-machine/states/plan-ready.d.ts.map +1 -1
  169. package/dist/state-machine/states/routing.d.ts.map +1 -1
  170. package/dist/state-machine/states/wave-planning.d.ts.map +1 -1
  171. package/dist/state-machine/workflow-projection.d.ts.map +1 -1
  172. package/dist/state-machine-execution-engine.d.ts +21 -9
  173. package/dist/state-machine-execution-engine.d.ts.map +1 -1
  174. package/dist/telemetry/state-capture.d.ts +5 -0
  175. package/dist/telemetry/state-capture.d.ts.map +1 -1
  176. package/dist/test-runner/core/flow-stage.d.ts.map +1 -1
  177. package/dist/test-runner/core/test-execution-wrapper.d.ts.map +1 -1
  178. package/dist/test-runner/evaluators.d.ts +37 -4
  179. package/dist/test-runner/evaluators.d.ts.map +1 -1
  180. package/dist/test-runner/index.d.ts +7 -0
  181. package/dist/test-runner/index.d.ts.map +1 -1
  182. package/dist/test-runner/recorders/slack-recorder.d.ts +17 -0
  183. package/dist/test-runner/recorders/slack-recorder.d.ts.map +1 -0
  184. package/dist/test-runner/validator.d.ts.map +1 -1
  185. package/dist/traces/{run-2025-11-21T11-50-46-505Z.ndjson โ†’ run-2026-01-21T05-37-24-446Z.ndjson} +91 -91
  186. package/dist/traces/run-2026-01-21T05-38-18-580Z.ndjson +1067 -0
  187. package/dist/types/bot.d.ts +109 -0
  188. package/dist/types/bot.d.ts.map +1 -0
  189. package/dist/types/cli.d.ts +4 -0
  190. package/dist/types/cli.d.ts.map +1 -1
  191. package/dist/types/config.d.ts +182 -5
  192. package/dist/types/config.d.ts.map +1 -1
  193. package/dist/types/engine.d.ts +5 -0
  194. package/dist/types/engine.d.ts.map +1 -1
  195. package/dist/types/git-checkout.d.ts +76 -0
  196. package/dist/types/git-checkout.d.ts.map +1 -0
  197. package/dist/utils/json-text-extractor.d.ts +17 -0
  198. package/dist/utils/json-text-extractor.d.ts.map +1 -0
  199. package/dist/utils/sandbox.d.ts +10 -0
  200. package/dist/utils/sandbox.d.ts.map +1 -1
  201. package/dist/utils/template-context.d.ts +1 -0
  202. package/dist/utils/template-context.d.ts.map +1 -1
  203. package/dist/utils/tracer-init.d.ts.map +1 -1
  204. package/dist/utils/workspace-manager.d.ts +118 -0
  205. package/dist/utils/workspace-manager.d.ts.map +1 -0
  206. package/dist/utils/worktree-cleanup.d.ts +33 -0
  207. package/dist/utils/worktree-cleanup.d.ts.map +1 -0
  208. package/dist/utils/worktree-manager.d.ts +153 -0
  209. package/dist/utils/worktree-manager.d.ts.map +1 -0
  210. package/dist/webhook-server.d.ts.map +1 -1
  211. package/dist/workflow-executor.d.ts.map +1 -1
  212. package/dist/workflow-registry.d.ts.map +1 -1
  213. package/package.json +5 -4
  214. package/dist/output/traces/run-2025-11-21T11-51-33-674Z.ndjson +0 -839
  215. package/dist/sdk/chunk-IEO6CFLG.mjs.map +0 -1
  216. package/dist/sdk/chunk-JEHPDJIF.mjs +0 -223
  217. package/dist/sdk/chunk-JEHPDJIF.mjs.map +0 -1
  218. package/dist/sdk/chunk-OZJ263FM.mjs.map +0 -1
  219. package/dist/sdk/chunk-PTL3K3PN.mjs.map +0 -1
  220. package/dist/sdk/chunk-VMPLF6FT.mjs.map +0 -1
  221. package/dist/sdk/github-frontend-4AWRJT7D.mjs.map +0 -1
  222. package/dist/sdk/host-7GBC3S7L.mjs.map +0 -1
  223. package/dist/sdk/memory-store-GJACZC2A.mjs +0 -11
  224. package/dist/sdk/workflow-registry-2YIIXQCK.mjs +0 -11
  225. package/dist/traces/run-2025-11-21T11-51-33-674Z.ndjson +0 -839
  226. /package/dist/sdk/{config-M4ZNO6NU.mjs.map โ†’ check-provider-registry-534KL5HT.mjs.map} +0 -0
  227. /package/dist/sdk/{chunk-37ZSCMFC.mjs.map โ†’ chunk-7UK3NIIT.mjs.map} +0 -0
  228. /package/dist/sdk/{chunk-6Y4YTKCF.mjs.map โ†’ chunk-NAW3DB3I.mjs.map} +0 -0
  229. /package/dist/sdk/{failure-condition-evaluator-NBO5YRXW.mjs.map โ†’ command-executor-TYUV6HUS.mjs.map} +0 -0
  230. /package/dist/sdk/{liquid-extensions-C7EG3YKH.mjs.map โ†’ config-YNC2EOOT.mjs.map} +0 -0
  231. /package/dist/sdk/{memory-store-GJACZC2A.mjs.map โ†’ failure-condition-evaluator-YGTF2GHG.mjs.map} +0 -0
  232. /package/dist/sdk/{routing-RP56JTV2.mjs.map โ†’ liquid-extensions-PKWCKK7E.mjs.map} +0 -0
  233. /package/dist/sdk/{session-registry-N5FFYFTM.mjs.map โ†’ memory-store-XGBB7LX7.mjs.map} +0 -0
  234. /package/dist/sdk/{tracer-init-WP4X46IF.mjs.map โ†’ prompt-state-YRJY6QAL.mjs.map} +0 -0
  235. /package/dist/sdk/{workflow-registry-2YIIXQCK.mjs.map โ†’ routing-6N45MJ4F.mjs.map} +0 -0
@@ -0,0 +1,261 @@
1
+ # Using Custom Tools with AI (Simple Guide)
2
+
3
+ ## TL;DR
4
+
5
+ You can expose custom shell-based tools to AI by adding `tools: [tool-names]` to your `ai_mcp_servers` configuration. No new config sections needed!
6
+
7
+ ```yaml
8
+ tools:
9
+ grep-pattern:
10
+ name: grep-pattern
11
+ exec: 'grep -rn "{{ args.pattern }}" *.ts'
12
+ inputSchema:
13
+ type: object
14
+ properties:
15
+ pattern: {type: string}
16
+ required: [pattern]
17
+
18
+ steps:
19
+ security-scan:
20
+ type: ai
21
+ prompt: Use grep-pattern to find security issues.
22
+ ai_mcp_servers:
23
+ custom-tools:
24
+ tools: [grep-pattern] # โ† Automatically creates ephemeral SSE MCP server!
25
+ ```
26
+
27
+ ## How It Works
28
+
29
+ When you add `tools: [...]` to an MCP server config:
30
+
31
+ 1. **Automatic Detection**: Visor detects you're referencing custom tools (not a command/URL)
32
+ 2. **Server Startup**: Creates an ephemeral SSE MCP server on an available port
33
+ 3. **Tool Exposure**: Your custom tools become available to the AI via MCP protocol
34
+ 4. **Auto Cleanup**: Server stops automatically when the AI check completes
35
+
36
+ ## Examples
37
+
38
+ ### Example 1: Security Scanning
39
+
40
+ ```yaml
41
+ tools:
42
+ check-secrets:
43
+ name: check-secrets
44
+ description: Scan for hardcoded secrets
45
+ exec: 'grep -rn -E "(api_key|secret|password)" .'
46
+ inputSchema:
47
+ type: object
48
+ properties: {}
49
+
50
+ steps:
51
+ security-review:
52
+ type: ai
53
+ prompt: Use check-secrets to find hardcoded credentials.
54
+ ai_mcp_servers:
55
+ security-tools:
56
+ tools: [check-secrets]
57
+ ```
58
+
59
+ ### Example 2: Multiple Custom Tools
60
+
61
+ ```yaml
62
+ tools:
63
+ grep-pattern:
64
+ name: grep-pattern
65
+ exec: 'grep -rn "{{ args.pattern }}" *.ts'
66
+ inputSchema:
67
+ type: object
68
+ properties:
69
+ pattern: {type: string}
70
+ required: [pattern]
71
+
72
+ count-todos:
73
+ name: count-todos
74
+ exec: 'grep -r "TODO" src/ | wc -l'
75
+ inputSchema:
76
+ type: object
77
+ properties: {}
78
+
79
+ steps:
80
+ code-quality:
81
+ type: ai
82
+ prompt: |
83
+ Use grep-pattern to find console.log statements.
84
+ Use count-todos to count pending work items.
85
+ ai_mcp_servers:
86
+ custom-tools:
87
+ tools: [grep-pattern, count-todos]
88
+ ```
89
+
90
+ ### Example 3: Combining Custom Tools with External MCP Servers
91
+
92
+ ```yaml
93
+ steps:
94
+ full-review:
95
+ type: ai
96
+ prompt: |
97
+ You have both custom tools and external MCP servers.
98
+ Use them for a comprehensive review.
99
+ ai_mcp_servers:
100
+ # Custom tools via ephemeral SSE server
101
+ my-tools:
102
+ tools: [grep-pattern, check-secrets]
103
+ # External MCP server via stdio
104
+ filesystem:
105
+ command: npx
106
+ args: ["-y", "@modelcontextprotocol/server-filesystem", "."]
107
+ ```
108
+
109
+ ## Configuration Format
110
+
111
+ ### Custom Tools Server (Ephemeral SSE)
112
+
113
+ ```yaml
114
+ ai_mcp_servers:
115
+ <server-name>:
116
+ tools: [tool-name-1, tool-name-2, ...]
117
+ ```
118
+
119
+ **Key points:**
120
+ - Server name can be anything (e.g., `custom-tools`, `my-tools`, `security-tools`)
121
+ - Tools must be defined in global `tools:` section
122
+ - Automatically creates SSE server on ephemeral port
123
+ - No command/URL needed - handled automatically
124
+
125
+ ### External MCP Server (Traditional)
126
+
127
+ ```yaml
128
+ ai_mcp_servers:
129
+ <server-name>:
130
+ command: <command>
131
+ args: [<arg1>, <arg2>, ...]
132
+ ```
133
+
134
+ **Key points:**
135
+ - Requires command to run external MCP server
136
+ - Uses stdio transport by default
137
+ - Can also use SSE/HTTP with `url:` and `transport:`
138
+
139
+ ## Backward Compatibility
140
+
141
+ The old `ai_custom_tools` field still works for backward compatibility:
142
+
143
+ ```yaml
144
+ steps:
145
+ my-check:
146
+ type: ai
147
+ ai_custom_tools: [tool1, tool2] # Still works!
148
+ ```
149
+
150
+ But the **recommended approach** is to use `ai_mcp_servers` with `tools:` because:
151
+ - โœ… Consistent with existing MCP server configuration
152
+ - โœ… No new config fields to learn
153
+ - โœ… Easier to combine custom + external MCP servers
154
+ - โœ… More flexible (can name your tool server)
155
+
156
+ ## Complete Example
157
+
158
+ ```yaml
159
+ version: "1.0"
160
+
161
+ # Define custom tools (global section)
162
+ tools:
163
+ grep-security:
164
+ name: grep-security
165
+ description: Search for security-related patterns
166
+ inputSchema:
167
+ type: object
168
+ properties:
169
+ pattern: {type: string}
170
+ required: [pattern]
171
+ exec: 'grep -rn "{{ args.pattern }}" src/'
172
+ parseJson: false
173
+
174
+ scan-dependencies:
175
+ name: scan-dependencies
176
+ description: Check for outdated dependencies
177
+ inputSchema:
178
+ type: object
179
+ properties: {}
180
+ exec: 'npm outdated --json 2>/dev/null || echo "{}"'
181
+ parseJson: true
182
+
183
+ count-lines:
184
+ name: count-lines
185
+ description: Count lines of code
186
+ inputSchema:
187
+ type: object
188
+ properties:
189
+ extension: {type: string}
190
+ required: [extension]
191
+ exec: 'find . -name "*.{{ args.extension }}" -exec wc -l {} + | tail -1'
192
+ parseJson: false
193
+
194
+ # Use custom tools in AI checks
195
+ steps:
196
+ security-audit:
197
+ type: ai
198
+ prompt: |
199
+ Perform a security audit:
200
+ 1. Use grep-security to find eval(), exec(), or dangerous patterns
201
+ 2. Use scan-dependencies to check for outdated packages
202
+ 3. Report findings with severity levels
203
+ ai_mcp_servers:
204
+ security-tools:
205
+ tools: [grep-security, scan-dependencies]
206
+ ai:
207
+ provider: anthropic
208
+ model: claude-3-5-sonnet-20241022
209
+
210
+ code-metrics:
211
+ type: ai
212
+ prompt: |
213
+ Analyze code metrics:
214
+ - Use count-lines to measure TypeScript code
215
+ - Provide insights on code size and complexity
216
+ ai_mcp_servers:
217
+ metrics-tools:
218
+ tools: [count-lines]
219
+ ai:
220
+ provider: anthropic
221
+ model: claude-3-5-sonnet-20241022
222
+
223
+ output:
224
+ pr_comment:
225
+ enabled: true
226
+ format: markdown
227
+ group_by: check
228
+ collapse: false
229
+ ```
230
+
231
+ ## Troubleshooting
232
+
233
+ ### "Custom tool not found"
234
+
235
+ **Problem**: `Custom tool not found: my-tool`
236
+
237
+ **Solution**: Make sure the tool is defined in the global `tools:` section with the exact same name.
238
+
239
+ ### "Failed to start custom tools SSE server"
240
+
241
+ **Problem**: Server fails to start
242
+
243
+ **Solutions**:
244
+ - Check if ports are available
245
+ - Verify tool definitions are valid
246
+ - Enable debug mode: `ai.debug: true`
247
+
248
+ ### Tools not appearing to AI
249
+
250
+ **Problem**: AI says it doesn't have access to tools
251
+
252
+ **Solutions**:
253
+ - Verify `tools:` field in `ai_mcp_servers` (not `tool` singular)
254
+ - Check tool names match exactly (case-sensitive)
255
+ - Enable debug logging to see server startup
256
+
257
+ ## See Also
258
+
259
+ - Full documentation: `docs/ai-custom-tools.md`
260
+ - Examples: `examples/ai-custom-tools-simple.yaml`
261
+ - Advanced examples: `examples/ai-custom-tools-example.yaml`
@@ -0,0 +1,392 @@
1
+ # AI Custom Tools via Ephemeral SSE MCP Servers
2
+
3
+ ## Overview
4
+
5
+ This feature allows AI checks to use custom shell-based tools defined in your Visor configuration. Custom tools are automatically exposed to AI via ephemeral SSE (Server-Sent Events) MCP (Model Context Protocol) servers that start on-demand and clean up automatically.
6
+
7
+ ## Key Benefits
8
+
9
+ โœ… **Zero Configuration**: Ports are automatically assigned by the OS
10
+ โœ… **Automatic Lifecycle**: Servers start before AI execution and clean up after
11
+ โœ… **Seamless Integration**: Works with existing AI providers (Anthropic, OpenAI, Gemini)
12
+ โœ… **Secure Execution**: Reuses existing tool security features
13
+ โœ… **Concurrent Support**: Multiple AI checks run independently with separate servers
14
+
15
+ ## How It Works
16
+
17
+ 1. **Define Tools**: Create custom tools in the `tools:` section of your config
18
+ 2. **Reference in AI Check**: Add `ai_custom_tools:` to your AI check configuration
19
+ 3. **Automatic Server**: Visor starts an ephemeral SSE MCP server on an available port
20
+ 4. **AI Execution**: AI can call your custom tools via the MCP protocol
21
+ 5. **Automatic Cleanup**: Server stops automatically when the AI check completes
22
+
23
+ ```
24
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
25
+ โ”‚ AI Check โ”‚
26
+ โ”‚ (Step 1) โ”‚
27
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜
28
+ โ”‚
29
+ โ”‚ ai_custom_tools: [grep, scan]
30
+ โ†“
31
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
32
+ โ”‚ AICheckProvider โ”‚
33
+ โ”‚ 1. Detect custom tools โ”‚
34
+ โ”‚ 2. Start SSE server (port) โ”‚
35
+ โ”‚ 3. Add to MCP servers โ”‚
36
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
37
+ โ”‚
38
+ โ†“
39
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
40
+ โ”‚ SSE MCP Server โ”‚
41
+ โ”‚ localhost:PORT โ”‚
42
+ โ”‚ โ”‚
43
+ โ”‚ Tools: โ”‚
44
+ โ”‚ - grep-tool โ”‚
45
+ โ”‚ - scan-tool โ”‚
46
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
47
+ โ†‘
48
+ โ”‚ MCP Protocol (tools/list, tools/call)
49
+ โ”‚
50
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
51
+ โ”‚ AI Provider โ”‚
52
+ โ”‚ (Claude, GPT) โ”‚
53
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
54
+ ```
55
+
56
+ ## Configuration
57
+
58
+ ### Basic Example
59
+
60
+ ```yaml
61
+ version: "1.0"
62
+
63
+ # Define custom tools
64
+ tools:
65
+ grep-pattern:
66
+ name: grep-pattern
67
+ description: Search for patterns in files
68
+ inputSchema:
69
+ type: object
70
+ properties:
71
+ pattern:
72
+ type: string
73
+ description: The regex pattern to search
74
+ required: [pattern]
75
+ exec: 'grep -rn "{{ args.pattern }}" *.ts'
76
+ parseJson: false
77
+
78
+ steps:
79
+ security-review:
80
+ type: ai
81
+ prompt: |
82
+ Use the grep-pattern tool to find potential security issues.
83
+ Search for: eval, exec, dangerouslySetInnerHTML
84
+ ai_custom_tools:
85
+ - grep-pattern # โ† Enable custom tool for this AI check
86
+ ai:
87
+ provider: anthropic
88
+ model: claude-3-5-sonnet-20241022
89
+ ```
90
+
91
+ ### Advanced Example with Multiple Tools
92
+
93
+ ```yaml
94
+ tools:
95
+ check-secrets:
96
+ name: check-secrets
97
+ description: Scan for hardcoded secrets
98
+ inputSchema:
99
+ type: object
100
+ properties:
101
+ file:
102
+ type: string
103
+ description: File to scan (optional)
104
+ exec: |
105
+ grep -rn -E "(api[_-]?key|secret|password)" {{ args.file | default: "." }}
106
+ parseJson: false
107
+ timeout: 10000
108
+
109
+ count-todos:
110
+ name: count-todos
111
+ description: Count TODO comments
112
+ inputSchema:
113
+ type: object
114
+ properties: {}
115
+ exec: 'grep -r "TODO" src/ | wc -l'
116
+ parseJson: false
117
+
118
+ file-stats:
119
+ name: file-stats
120
+ description: Get file statistics
121
+ inputSchema:
122
+ type: object
123
+ properties:
124
+ filename:
125
+ type: string
126
+ description: File to analyze
127
+ required: [filename]
128
+ exec: |
129
+ echo "Lines: $(wc -l < {{ args.filename }})"
130
+ echo "Size: $(wc -c < {{ args.filename }}) bytes"
131
+ parseJson: false
132
+
133
+ steps:
134
+ comprehensive-review:
135
+ type: ai
136
+ prompt: |
137
+ You have access to specialized analysis tools:
138
+ - check-secrets: Scan for hardcoded credentials
139
+ - count-todos: Count pending work items
140
+ - file-stats: Analyze file statistics
141
+
142
+ Use these tools to provide a comprehensive code review.
143
+ ai_custom_tools:
144
+ - check-secrets
145
+ - count-todos
146
+ - file-stats
147
+ ai:
148
+ provider: anthropic
149
+ model: claude-3-5-sonnet-20241022
150
+ debug: true
151
+ ```
152
+
153
+ ### Combining with External MCP Servers
154
+
155
+ You can combine custom tools with external MCP servers:
156
+
157
+ ```yaml
158
+ steps:
159
+ full-review:
160
+ type: ai
161
+ prompt: |
162
+ You have both custom tools and external MCP servers available.
163
+ Use them strategically for a thorough review.
164
+ ai_custom_tools:
165
+ - grep-pattern
166
+ - check-secrets
167
+ ai_mcp_servers:
168
+ filesystem:
169
+ command: npx
170
+ args: ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
171
+ probe:
172
+ command: npx
173
+ args: ["-y", "@probelabs/probe@latest", "mcp"]
174
+ ```
175
+
176
+ ## Tool Definition Reference
177
+
178
+ ### Required Fields
179
+
180
+ - `name`: Unique identifier for the tool
181
+ - `exec`: Shell command to execute (supports Liquid templates)
182
+ - `inputSchema`: JSON Schema defining the tool's input parameters
183
+
184
+ ### Optional Fields
185
+
186
+ - `description`: Human-readable description of what the tool does
187
+ - `parseJson`: Whether to parse the command output as JSON (default: false)
188
+ - `timeout`: Execution timeout in milliseconds (default: 30000)
189
+ - `stdin`: Optional input to pass to the command
190
+ - `transform`: Liquid template to transform the output
191
+ - `transform_js`: JavaScript expression to transform the output
192
+ - `cwd`: Working directory for command execution
193
+ - `env`: Environment variables to set
194
+
195
+ ### Input Schema
196
+
197
+ The `inputSchema` uses JSON Schema format to define tool parameters:
198
+
199
+ ```yaml
200
+ inputSchema:
201
+ type: object
202
+ properties:
203
+ pattern:
204
+ type: string
205
+ description: Pattern to search for
206
+ files:
207
+ type: string
208
+ description: File glob pattern
209
+ default: "*.ts"
210
+ required: [pattern] # List of required parameters
211
+ ```
212
+
213
+ ### Liquid Templates
214
+
215
+ You can use Liquid templates in `exec`, `stdin`, and `transform`:
216
+
217
+ ```yaml
218
+ exec: 'grep -n "{{ args.pattern }}" {{ args.files | default: "*.ts" }}'
219
+ ```
220
+
221
+ Available variables:
222
+ - `args`: Tool input arguments
223
+ - `pr`: PR information (if available)
224
+ - `files`: Changed files (if available)
225
+ - `outputs`: Outputs from previous checks
226
+ - `env`: Environment variables
227
+
228
+ ## Security Considerations
229
+
230
+ Custom tools run with the same security constraints as other command providers:
231
+
232
+ 1. **Command Injection Protection**: Input validation via JSON Schema
233
+ 2. **Sandboxed Execution**: Tools run in isolated processes
234
+ 3. **Timeout Enforcement**: All tools have configurable timeouts
235
+ 4. **Localhost Only**: SSE servers bind only to localhost
236
+ 5. **No Credential Storage**: Servers don't store authentication data
237
+
238
+ ## Troubleshooting
239
+
240
+ ### Server Won't Start
241
+
242
+ **Problem**: `Failed to start custom tools SSE server`
243
+
244
+ **Solutions**:
245
+ - Check if ports are available (firewall/permissions)
246
+ - Verify tools are defined in global `tools:` section
247
+ - Enable debug mode: `ai.debug: true`
248
+
249
+ ### Tool Not Found
250
+
251
+ **Problem**: `Custom tool not found: <tool-name>`
252
+
253
+ **Solutions**:
254
+ - Verify tool name matches exactly (case-sensitive)
255
+ - Check tool is defined in global `tools:` section
256
+ - Ensure `ai_custom_tools` references correct tool name
257
+
258
+ ### Tool Execution Timeout
259
+
260
+ **Problem**: Tool calls timeout
261
+
262
+ **Solutions**:
263
+ - Increase tool timeout: `timeout: 60000` (60 seconds)
264
+ - Simplify the tool command
265
+ - Check command is not blocking on input
266
+
267
+ ### Debug Mode
268
+
269
+ Enable debug logging to see detailed server operations:
270
+
271
+ ```yaml
272
+ steps:
273
+ my-check:
274
+ type: ai
275
+ ai_custom_tools: [my-tool]
276
+ ai:
277
+ debug: true # โ† Enable debug logging
278
+ ```
279
+
280
+ You'll see:
281
+ - Server startup messages
282
+ - Port assignment
283
+ - Tool execution logs
284
+ - Cleanup operations
285
+
286
+ ## Performance
287
+
288
+ - **Server Startup**: < 100ms
289
+ - **Tool Execution**: Inherits timeout from tool config (default: 30s)
290
+ - **Server Shutdown**: < 1s graceful, 5s forced
291
+ - **Memory Overhead**: Minimal per server instance
292
+ - **Concurrent Requests**: Queued (one at a time per server)
293
+
294
+ ## Implementation Details
295
+
296
+ ### Components
297
+
298
+ 1. **CustomToolsSSEServer** (`src/providers/mcp-custom-sse-server.ts`)
299
+ - HTTP server with SSE endpoint
300
+ - MCP protocol implementation
301
+ - Tool execution via CustomToolExecutor
302
+
303
+ 2. **AICheckProvider Integration** (`src/providers/ai-check-provider.ts`)
304
+ - Automatic tool detection
305
+ - Server lifecycle management
306
+ - MCP server configuration injection
307
+
308
+ 3. **Configuration Types** (`src/types/config.ts`)
309
+ - `ai_custom_tools?: string[]` field on CheckConfig
310
+
311
+ ### MCP Protocol Support
312
+
313
+ The server implements these MCP methods:
314
+
315
+ - `initialize`: Connection initialization
316
+ - `tools/list`: List available tools
317
+ - `tools/call`: Execute a tool
318
+ - `notifications/initialized`: Initialization confirmation
319
+
320
+ Message format: JSON-RPC 2.0
321
+
322
+ ### Lifecycle Management
323
+
324
+ ```typescript
325
+ // Pseudo-code of lifecycle
326
+ const server = new CustomToolsSSEServer(tools, sessionId, debug);
327
+
328
+ try {
329
+ const port = await server.start(); // OS assigns port
330
+ // ... AI execution with tools ...
331
+ } finally {
332
+ await server.stop(); // Always cleanup
333
+ }
334
+ ```
335
+
336
+ ## Examples
337
+
338
+ See `examples/ai-custom-tools-example.yaml` for a comprehensive example with:
339
+ - Security scanning tools
340
+ - Code quality tools
341
+ - File analysis tools
342
+ - Git integration tools
343
+ - Combined custom + external MCP servers
344
+
345
+ ## Testing
346
+
347
+ Run the manual test to verify functionality:
348
+
349
+ ```bash
350
+ npx ts-node manual-test-simple.ts
351
+ ```
352
+
353
+ Expected output:
354
+ ```
355
+ ============================================================
356
+ ๐Ÿงช CustomToolsSSEServer - Quick Manual Test
357
+ ============================================================
358
+
359
+ 1๏ธโƒฃ Starting SSE server...
360
+ โœ… Server running on http://localhost:58869/sse
361
+
362
+ 2๏ธโƒฃ Calling echo-tool with message...
363
+ โœ… Response: โœ… Tool works: Hello from custom tools!
364
+
365
+ 3๏ธโƒฃ Calling pwd-tool...
366
+ โœ… Working directory: /path/to/project
367
+
368
+ 4๏ธโƒฃ Testing error handling (invalid tool)...
369
+ โœ… Error correctly returned: Internal error
370
+
371
+ ============================================================
372
+ โœ… ALL TESTS PASSED! Feature is working correctly! ๐ŸŽ‰
373
+ ============================================================
374
+ ```
375
+
376
+ ## Future Enhancements
377
+
378
+ Potential improvements:
379
+ - Tool result caching
380
+ - Parallel tool execution
381
+ - Tool dependencies
382
+ - Tool composition (chaining)
383
+ - Persistent MCP servers (optional)
384
+ - Tool metrics and monitoring
385
+
386
+ ## Support
387
+
388
+ For issues or questions:
389
+ - Check troubleshooting section above
390
+ - Enable debug mode for detailed logs
391
+ - Review test files in `tests/unit/mcp-custom-sse-server.test.ts`
392
+ - See examples in `examples/ai-custom-tools-example.yaml`
@@ -0,0 +1,23 @@
1
+ # RFC: Bot Transports for Visor (Slack-first)
2
+
3
+ Status: Draft
4
+
5
+ This RFC proposes a Slack integration built on the event-bus/state-machine engine. The first iteration focuses on:
6
+ - A Slack frontend that subscribes to engine events and posts an evolving message per group (e.g., overview, review).
7
+ - Simple configuration via `frontends` in the workflow config, e.g.
8
+
9
+ ```
10
+ frontends:
11
+ - name: slack
12
+ config:
13
+ defaultChannel: C12345678
14
+ groupChannels:
15
+ overview: C87654321
16
+ ```
17
+
18
+ Design notes:
19
+ - No placeholder/queued messages are posted; only content-producing events produce/modify messages.
20
+ - Messages are updated in-place (using `chat.update`) keyed by group. We do not rely on hidden markers in message text.
21
+ - Debounce/coalescing reduces API churn during bursts; terminal state forces an immediate flush.
22
+ - Future work will add inbound Slack handling (webhooks) to trigger workflows and attach conversation context.
23
+
@@ -81,6 +81,27 @@ steps:
81
81
  prompt: "Analyze code for security vulnerabilities"
82
82
  ```
83
83
 
84
+ ### Lifecycle Hooks
85
+
86
+ Use `on_init` to run preprocessing tasks before a step executes:
87
+
88
+ ```yaml
89
+ steps:
90
+ ai-review:
91
+ type: ai
92
+ on_init:
93
+ run:
94
+ - tool: fetch-jira-issue
95
+ with:
96
+ issue_key: "{{ pr.title | regex_search: '[A-Z]+-[0-9]+' }}"
97
+ as: jira-data
98
+ prompt: |
99
+ Review this PR considering JIRA issue context:
100
+ {{ outputs['jira-data'] | json }}
101
+ ```
102
+
103
+ See [Lifecycle Hooks](./lifecycle-hooks.md) for complete documentation.
104
+
84
105
  ### Environment Variables
85
106
 
86
107
  Inject environment variables globally or per-check via `env`: