@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.
- package/README.md +6 -0
- package/defaults/task-refinement.yaml +7 -3
- package/defaults/visor.tests.yaml +13 -2
- package/defaults/visor.yaml +1 -0
- package/dist/663.index.js +3 -2
- package/dist/80.index.js +3 -2
- package/dist/ai-review-service.d.ts +13 -9
- package/dist/ai-review-service.d.ts.map +1 -1
- package/dist/cli-main.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/debug-visualizer/ws-server.d.ts +7 -1
- package/dist/debug-visualizer/ws-server.d.ts.map +1 -1
- package/dist/defaults/task-refinement.yaml +7 -3
- package/dist/defaults/visor.tests.yaml +13 -2
- package/dist/defaults/visor.yaml +1 -0
- package/dist/docs/advanced-ai.md +60 -1
- package/dist/docs/ai-configuration.md +67 -0
- package/dist/docs/ai-custom-tools-usage.md +261 -0
- package/dist/docs/ai-custom-tools.md +392 -0
- package/dist/docs/bot-transports-rfc.md +23 -0
- package/dist/docs/configuration.md +21 -0
- package/dist/docs/engine-pause-resume-rfc.md +192 -0
- package/dist/docs/lifecycle-hooks.md +253 -0
- package/dist/docs/liquid-templates.md +143 -0
- package/dist/docs/providers/git-checkout.md +589 -0
- package/dist/docs/recipes.md +458 -5
- package/dist/docs/rfc/git-checkout-step.md +601 -0
- package/dist/docs/rfc/on_init-hook.md +1294 -0
- package/dist/docs/rfc/workspace-isolation.md +216 -0
- package/dist/docs/router-patterns.md +339 -0
- package/dist/event-bus/types.d.ts +14 -0
- package/dist/event-bus/types.d.ts.map +1 -1
- package/dist/examples/ai-custom-tools-example.yaml +206 -0
- package/dist/examples/ai-custom-tools-simple.yaml +76 -0
- package/dist/examples/git-checkout-basic.yaml +32 -0
- package/dist/examples/git-checkout-compare.yaml +59 -0
- package/dist/examples/git-checkout-cross-repo.yaml +76 -0
- package/dist/examples/on-init-import-demo.yaml +179 -0
- package/dist/examples/reusable-tools.yaml +92 -0
- package/dist/examples/reusable-workflows.yaml +88 -0
- package/dist/examples/session-reuse-self.yaml +81 -0
- package/dist/examples/slack-simple-chat.yaml +775 -0
- package/dist/failure-condition-evaluator.d.ts +2 -0
- package/dist/failure-condition-evaluator.d.ts.map +1 -1
- package/dist/frontends/github-frontend.d.ts +20 -0
- package/dist/frontends/github-frontend.d.ts.map +1 -1
- package/dist/frontends/host.d.ts +4 -0
- package/dist/frontends/host.d.ts.map +1 -1
- package/dist/frontends/slack-frontend.d.ts +58 -0
- package/dist/frontends/slack-frontend.d.ts.map +1 -0
- package/dist/generated/config-schema.d.ts +409 -41
- package/dist/generated/config-schema.d.ts.map +1 -1
- package/dist/generated/config-schema.json +436 -47
- package/dist/github-comments.d.ts +2 -0
- package/dist/github-comments.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +83587 -56085
- package/dist/liquid-extensions.d.ts.map +1 -1
- package/dist/logger.d.ts +1 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/output/traces/{run-2025-11-21T11-50-46-505Z.ndjson โ run-2026-01-21T05-37-24-446Z.ndjson} +91 -91
- package/dist/output/traces/run-2026-01-21T05-38-18-580Z.ndjson +1067 -0
- package/dist/output-formatters.d.ts.map +1 -1
- package/dist/providers/ai-check-provider.d.ts +12 -0
- package/dist/providers/ai-check-provider.d.ts.map +1 -1
- package/dist/providers/check-provider-registry.d.ts.map +1 -1
- package/dist/providers/check-provider.interface.d.ts +9 -0
- package/dist/providers/check-provider.interface.d.ts.map +1 -1
- package/dist/providers/command-check-provider.d.ts.map +1 -1
- package/dist/providers/custom-tool-executor.d.ts.map +1 -1
- package/dist/providers/git-checkout-provider.d.ts +25 -0
- package/dist/providers/git-checkout-provider.d.ts.map +1 -0
- package/dist/providers/http-client-provider.d.ts +3 -0
- package/dist/providers/http-client-provider.d.ts.map +1 -1
- package/dist/providers/human-input-check-provider.d.ts +2 -0
- package/dist/providers/human-input-check-provider.d.ts.map +1 -1
- package/dist/providers/log-check-provider.d.ts.map +1 -1
- package/dist/providers/mcp-check-provider.d.ts +1 -1
- package/dist/providers/mcp-check-provider.d.ts.map +1 -1
- package/dist/providers/mcp-custom-sse-server.d.ts +66 -0
- package/dist/providers/mcp-custom-sse-server.d.ts.map +1 -0
- package/dist/providers/memory-check-provider.d.ts.map +1 -1
- package/dist/providers/script-check-provider.d.ts.map +1 -1
- package/dist/providers/workflow-check-provider.d.ts.map +1 -1
- package/dist/reviewer.d.ts.map +1 -1
- package/dist/sdk/check-provider-registry-534KL5HT.mjs +27 -0
- package/dist/sdk/chunk-23L3QRYX.mjs +16872 -0
- package/dist/sdk/chunk-23L3QRYX.mjs.map +1 -0
- package/dist/sdk/{chunk-OOZITMRU.mjs โ chunk-3OMWVM6J.mjs} +11 -1
- package/dist/sdk/{chunk-OOZITMRU.mjs.map โ chunk-3OMWVM6J.mjs.map} +1 -1
- package/dist/sdk/{chunk-37ZSCMFC.mjs โ chunk-7UK3NIIT.mjs} +2 -2
- package/dist/sdk/{chunk-VMPLF6FT.mjs โ chunk-AGIZJ4UZ.mjs} +50 -4
- package/dist/sdk/chunk-AGIZJ4UZ.mjs.map +1 -0
- package/dist/sdk/{chunk-IEO6CFLG.mjs โ chunk-AIVFBIS4.mjs} +161 -5
- package/dist/sdk/chunk-AIVFBIS4.mjs.map +1 -0
- package/dist/sdk/chunk-AK6BVWIT.mjs +426 -0
- package/dist/sdk/chunk-AK6BVWIT.mjs.map +1 -0
- package/dist/sdk/chunk-AUT26LHW.mjs +139 -0
- package/dist/sdk/chunk-AUT26LHW.mjs.map +1 -0
- package/dist/sdk/chunk-BOVFH3LI.mjs +232 -0
- package/dist/sdk/chunk-BOVFH3LI.mjs.map +1 -0
- package/dist/sdk/chunk-HTOKWMPO.mjs +157 -0
- package/dist/sdk/chunk-HTOKWMPO.mjs.map +1 -0
- package/dist/sdk/{chunk-6Y4YTKCF.mjs โ chunk-NAW3DB3I.mjs} +2 -2
- package/dist/sdk/{chunk-OWUVOILT.mjs โ chunk-QR7MOMJH.mjs} +4 -3
- package/dist/sdk/{chunk-OWUVOILT.mjs.map โ chunk-QR7MOMJH.mjs.map} +1 -1
- package/dist/sdk/{chunk-PTL3K3PN.mjs โ chunk-QY2XYPEV.mjs} +488 -60
- package/dist/sdk/chunk-QY2XYPEV.mjs.map +1 -0
- package/dist/sdk/{chunk-OZJ263FM.mjs โ chunk-SIWNBRTK.mjs} +29 -215
- package/dist/sdk/chunk-SIWNBRTK.mjs.map +1 -0
- package/dist/sdk/command-executor-TYUV6HUS.mjs +14 -0
- package/dist/sdk/{config-M4ZNO6NU.mjs โ config-YNC2EOOT.mjs} +5 -3
- package/dist/sdk/{failure-condition-evaluator-NBO5YRXW.mjs โ failure-condition-evaluator-YGTF2GHG.mjs} +6 -5
- package/dist/sdk/{github-frontend-4AWRJT7D.mjs โ github-frontend-SIAEOCON.mjs} +190 -12
- package/dist/sdk/github-frontend-SIAEOCON.mjs.map +1 -0
- package/dist/sdk/{host-7GBC3S7L.mjs โ host-DXUYTNMU.mjs} +5 -2
- package/dist/sdk/host-DXUYTNMU.mjs.map +1 -0
- package/dist/sdk/{liquid-extensions-C7EG3YKH.mjs โ liquid-extensions-PKWCKK7E.mjs} +5 -4
- package/dist/sdk/memory-store-XGBB7LX7.mjs +12 -0
- package/dist/sdk/prompt-state-YRJY6QAL.mjs +16 -0
- package/dist/sdk/{renderer-schema-6RF26VUS.mjs โ renderer-schema-LPKN5UJS.mjs} +3 -2
- package/dist/sdk/{renderer-schema-6RF26VUS.mjs.map โ renderer-schema-LPKN5UJS.mjs.map} +1 -1
- package/dist/sdk/{routing-RP56JTV2.mjs โ routing-6N45MJ4F.mjs} +7 -6
- package/dist/sdk/sdk.d.mts +219 -5
- package/dist/sdk/sdk.d.ts +219 -5
- package/dist/sdk/sdk.js +21329 -14908
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +407 -12874
- package/dist/sdk/sdk.mjs.map +1 -1
- package/dist/sdk/{session-registry-N5FFYFTM.mjs โ session-registry-4E6YRQ77.mjs} +2 -2
- package/dist/sdk/session-registry-4E6YRQ77.mjs.map +1 -0
- package/dist/sdk/slack-frontend-BVKW3GD5.mjs +735 -0
- package/dist/sdk/slack-frontend-BVKW3GD5.mjs.map +1 -0
- package/dist/sdk/{tracer-init-WP4X46IF.mjs โ tracer-init-GSLPPLCD.mjs} +2 -2
- package/dist/sdk/tracer-init-GSLPPLCD.mjs.map +1 -0
- package/dist/sdk/workflow-registry-R6KSACFR.mjs +12 -0
- package/dist/sdk/workflow-registry-R6KSACFR.mjs.map +1 -0
- package/dist/slack/adapter.d.ts +36 -0
- package/dist/slack/adapter.d.ts.map +1 -0
- package/dist/slack/cache-prewarmer.d.ts +31 -0
- package/dist/slack/cache-prewarmer.d.ts.map +1 -0
- package/dist/slack/client.d.ts +77 -0
- package/dist/slack/client.d.ts.map +1 -0
- package/dist/slack/markdown.d.ts +45 -0
- package/dist/slack/markdown.d.ts.map +1 -0
- package/dist/slack/prompt-state.d.ts +33 -0
- package/dist/slack/prompt-state.d.ts.map +1 -0
- package/dist/slack/rate-limiter.d.ts +56 -0
- package/dist/slack/rate-limiter.d.ts.map +1 -0
- package/dist/slack/signature.d.ts +2 -0
- package/dist/slack/signature.d.ts.map +1 -0
- package/dist/slack/socket-runner.d.ts +42 -0
- package/dist/slack/socket-runner.d.ts.map +1 -0
- package/dist/slack/thread-cache.d.ts +51 -0
- package/dist/slack/thread-cache.d.ts.map +1 -0
- package/dist/state-machine/context/build-engine-context.d.ts +8 -0
- package/dist/state-machine/context/build-engine-context.d.ts.map +1 -1
- package/dist/state-machine/dispatch/execution-invoker.d.ts.map +1 -1
- package/dist/state-machine/dispatch/foreach-processor.d.ts.map +1 -1
- package/dist/state-machine/dispatch/on-init-handlers.d.ts +43 -0
- package/dist/state-machine/dispatch/on-init-handlers.d.ts.map +1 -0
- package/dist/state-machine/dispatch/stats-manager.d.ts.map +1 -1
- package/dist/state-machine/dispatch/template-renderer.d.ts.map +1 -1
- package/dist/state-machine/runner.d.ts +6 -0
- package/dist/state-machine/runner.d.ts.map +1 -1
- package/dist/state-machine/states/level-dispatch.d.ts.map +1 -1
- package/dist/state-machine/states/plan-ready.d.ts.map +1 -1
- package/dist/state-machine/states/routing.d.ts.map +1 -1
- package/dist/state-machine/states/wave-planning.d.ts.map +1 -1
- package/dist/state-machine/workflow-projection.d.ts.map +1 -1
- package/dist/state-machine-execution-engine.d.ts +21 -9
- package/dist/state-machine-execution-engine.d.ts.map +1 -1
- package/dist/telemetry/state-capture.d.ts +5 -0
- package/dist/telemetry/state-capture.d.ts.map +1 -1
- package/dist/test-runner/core/flow-stage.d.ts.map +1 -1
- package/dist/test-runner/core/test-execution-wrapper.d.ts.map +1 -1
- package/dist/test-runner/evaluators.d.ts +37 -4
- package/dist/test-runner/evaluators.d.ts.map +1 -1
- package/dist/test-runner/index.d.ts +7 -0
- package/dist/test-runner/index.d.ts.map +1 -1
- package/dist/test-runner/recorders/slack-recorder.d.ts +17 -0
- package/dist/test-runner/recorders/slack-recorder.d.ts.map +1 -0
- package/dist/test-runner/validator.d.ts.map +1 -1
- package/dist/traces/{run-2025-11-21T11-50-46-505Z.ndjson โ run-2026-01-21T05-37-24-446Z.ndjson} +91 -91
- package/dist/traces/run-2026-01-21T05-38-18-580Z.ndjson +1067 -0
- package/dist/types/bot.d.ts +109 -0
- package/dist/types/bot.d.ts.map +1 -0
- package/dist/types/cli.d.ts +4 -0
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/config.d.ts +182 -5
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/engine.d.ts +5 -0
- package/dist/types/engine.d.ts.map +1 -1
- package/dist/types/git-checkout.d.ts +76 -0
- package/dist/types/git-checkout.d.ts.map +1 -0
- package/dist/utils/json-text-extractor.d.ts +17 -0
- package/dist/utils/json-text-extractor.d.ts.map +1 -0
- package/dist/utils/sandbox.d.ts +10 -0
- package/dist/utils/sandbox.d.ts.map +1 -1
- package/dist/utils/template-context.d.ts +1 -0
- package/dist/utils/template-context.d.ts.map +1 -1
- package/dist/utils/tracer-init.d.ts.map +1 -1
- package/dist/utils/workspace-manager.d.ts +118 -0
- package/dist/utils/workspace-manager.d.ts.map +1 -0
- package/dist/utils/worktree-cleanup.d.ts +33 -0
- package/dist/utils/worktree-cleanup.d.ts.map +1 -0
- package/dist/utils/worktree-manager.d.ts +153 -0
- package/dist/utils/worktree-manager.d.ts.map +1 -0
- package/dist/webhook-server.d.ts.map +1 -1
- package/dist/workflow-executor.d.ts.map +1 -1
- package/dist/workflow-registry.d.ts.map +1 -1
- package/package.json +5 -4
- package/dist/output/traces/run-2025-11-21T11-51-33-674Z.ndjson +0 -839
- package/dist/sdk/chunk-IEO6CFLG.mjs.map +0 -1
- package/dist/sdk/chunk-JEHPDJIF.mjs +0 -223
- package/dist/sdk/chunk-JEHPDJIF.mjs.map +0 -1
- package/dist/sdk/chunk-OZJ263FM.mjs.map +0 -1
- package/dist/sdk/chunk-PTL3K3PN.mjs.map +0 -1
- package/dist/sdk/chunk-VMPLF6FT.mjs.map +0 -1
- package/dist/sdk/github-frontend-4AWRJT7D.mjs.map +0 -1
- package/dist/sdk/host-7GBC3S7L.mjs.map +0 -1
- package/dist/sdk/memory-store-GJACZC2A.mjs +0 -11
- package/dist/sdk/workflow-registry-2YIIXQCK.mjs +0 -11
- package/dist/traces/run-2025-11-21T11-51-33-674Z.ndjson +0 -839
- /package/dist/sdk/{config-M4ZNO6NU.mjs.map โ check-provider-registry-534KL5HT.mjs.map} +0 -0
- /package/dist/sdk/{chunk-37ZSCMFC.mjs.map โ chunk-7UK3NIIT.mjs.map} +0 -0
- /package/dist/sdk/{chunk-6Y4YTKCF.mjs.map โ chunk-NAW3DB3I.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-NBO5YRXW.mjs.map โ command-executor-TYUV6HUS.mjs.map} +0 -0
- /package/dist/sdk/{liquid-extensions-C7EG3YKH.mjs.map โ config-YNC2EOOT.mjs.map} +0 -0
- /package/dist/sdk/{memory-store-GJACZC2A.mjs.map โ failure-condition-evaluator-YGTF2GHG.mjs.map} +0 -0
- /package/dist/sdk/{routing-RP56JTV2.mjs.map โ liquid-extensions-PKWCKK7E.mjs.map} +0 -0
- /package/dist/sdk/{session-registry-N5FFYFTM.mjs.map โ memory-store-XGBB7LX7.mjs.map} +0 -0
- /package/dist/sdk/{tracer-init-WP4X46IF.mjs.map โ prompt-state-YRJY6QAL.mjs.map} +0 -0
- /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`:
|