@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,206 @@
|
|
|
1
|
+
version: "1.0"
|
|
2
|
+
|
|
3
|
+
# Example: Using Custom Tools with AI Checks
|
|
4
|
+
# This demonstrates how to expose custom shell-based tools to AI via ephemeral SSE MCP servers
|
|
5
|
+
|
|
6
|
+
# Define custom tools that AI can use
|
|
7
|
+
tools:
|
|
8
|
+
# Tool 1: Search for patterns in code
|
|
9
|
+
grep-pattern:
|
|
10
|
+
name: grep-pattern
|
|
11
|
+
description: Search for specific patterns in TypeScript files
|
|
12
|
+
inputSchema:
|
|
13
|
+
type: object
|
|
14
|
+
properties:
|
|
15
|
+
pattern:
|
|
16
|
+
type: string
|
|
17
|
+
description: The pattern to search for (regex supported)
|
|
18
|
+
files:
|
|
19
|
+
type: string
|
|
20
|
+
description: File glob pattern (default is *.ts)
|
|
21
|
+
required: [pattern]
|
|
22
|
+
exec: |
|
|
23
|
+
grep -rn "{{ args.pattern }}" {{ args.files | default: "*.ts" }} 2>/dev/null || echo "No matches found"
|
|
24
|
+
parseJson: false
|
|
25
|
+
timeout: 5000
|
|
26
|
+
|
|
27
|
+
# Tool 2: Count TODO comments
|
|
28
|
+
count-todos:
|
|
29
|
+
name: count-todos
|
|
30
|
+
description: Count TODO, FIXME, and HACK comments in the codebase
|
|
31
|
+
inputSchema:
|
|
32
|
+
type: object
|
|
33
|
+
properties:
|
|
34
|
+
directory:
|
|
35
|
+
type: string
|
|
36
|
+
description: Directory to search (default is src/)
|
|
37
|
+
required: []
|
|
38
|
+
exec: |
|
|
39
|
+
echo "TODO: $(grep -r "TODO" {{ args.directory | default: "src/" }} 2>/dev/null | wc -l | tr -d ' ')"
|
|
40
|
+
echo "FIXME: $(grep -r "FIXME" {{ args.directory | default: "src/" }} 2>/dev/null | wc -l | tr -d ' ')"
|
|
41
|
+
echo "HACK: $(grep -r "HACK" {{ args.directory | default: "src/" }} 2>/dev/null | wc -l | tr -d ' ')"
|
|
42
|
+
parseJson: false
|
|
43
|
+
timeout: 10000
|
|
44
|
+
|
|
45
|
+
# Tool 3: Check for security issues
|
|
46
|
+
check-secrets:
|
|
47
|
+
name: check-secrets
|
|
48
|
+
description: Scan for potential hardcoded secrets and API keys
|
|
49
|
+
inputSchema:
|
|
50
|
+
type: object
|
|
51
|
+
properties:
|
|
52
|
+
file:
|
|
53
|
+
type: string
|
|
54
|
+
description: Specific file to check (optional)
|
|
55
|
+
required: []
|
|
56
|
+
exec: |
|
|
57
|
+
FILES="{{ args.file | default: '.' }}"
|
|
58
|
+
echo "Scanning for potential secrets in: $FILES"
|
|
59
|
+
grep -rn -E "(api[_-]?key|secret|password|token)\s*[:=]" $FILES 2>/dev/null | head -20 || echo "No obvious secrets found"
|
|
60
|
+
parseJson: false
|
|
61
|
+
timeout: 10000
|
|
62
|
+
|
|
63
|
+
# Tool 4: List recent git changes
|
|
64
|
+
git-recent-changes:
|
|
65
|
+
name: git-recent-changes
|
|
66
|
+
description: Get list of recently changed files
|
|
67
|
+
inputSchema:
|
|
68
|
+
type: object
|
|
69
|
+
properties:
|
|
70
|
+
count:
|
|
71
|
+
type: number
|
|
72
|
+
description: Number of commits to look back (default is 5)
|
|
73
|
+
required: []
|
|
74
|
+
exec: |
|
|
75
|
+
git log -{{ args.count | default: 5 }} --name-only --pretty=format:"Commit: %h - %s" 2>/dev/null || echo "Not a git repository"
|
|
76
|
+
parseJson: false
|
|
77
|
+
timeout: 5000
|
|
78
|
+
|
|
79
|
+
# Tool 5: Get file stats
|
|
80
|
+
file-stats:
|
|
81
|
+
name: file-stats
|
|
82
|
+
description: Get statistics about a specific file
|
|
83
|
+
inputSchema:
|
|
84
|
+
type: object
|
|
85
|
+
properties:
|
|
86
|
+
filename:
|
|
87
|
+
type: string
|
|
88
|
+
description: The file to analyze
|
|
89
|
+
required: [filename]
|
|
90
|
+
exec: |
|
|
91
|
+
if [ -f "{{ args.filename }}" ]; then
|
|
92
|
+
echo "File: {{ args.filename }}"
|
|
93
|
+
echo "Lines: $(wc -l < "{{ args.filename }}" | tr -d ' ')"
|
|
94
|
+
echo "Size: $(wc -c < "{{ args.filename }}" | tr -d ' ') bytes"
|
|
95
|
+
echo "Last modified: $(stat -f "%Sm" "{{ args.filename }}" 2>/dev/null || stat -c "%y" "{{ args.filename }}" 2>/dev/null)"
|
|
96
|
+
else
|
|
97
|
+
echo "Error: File not found - {{ args.filename }}"
|
|
98
|
+
fi
|
|
99
|
+
parseJson: false
|
|
100
|
+
timeout: 3000
|
|
101
|
+
|
|
102
|
+
# Define AI checks that use these custom tools
|
|
103
|
+
steps:
|
|
104
|
+
# Check 1: Security review using custom tools
|
|
105
|
+
security-scan:
|
|
106
|
+
type: ai
|
|
107
|
+
prompt: |
|
|
108
|
+
You are a security-focused code reviewer. You have access to specialized tools.
|
|
109
|
+
|
|
110
|
+
Your mission:
|
|
111
|
+
1. Use the 'check-secrets' tool to scan for hardcoded secrets
|
|
112
|
+
2. Use the 'grep-pattern' tool to find unsafe function calls like eval(), exec(), or system()
|
|
113
|
+
3. Report any security issues you find
|
|
114
|
+
|
|
115
|
+
Provide a security assessment with severity levels (critical, high, medium, low).
|
|
116
|
+
ai_custom_tools:
|
|
117
|
+
- check-secrets
|
|
118
|
+
- grep-pattern
|
|
119
|
+
ai:
|
|
120
|
+
provider: anthropic
|
|
121
|
+
model: claude-3-5-sonnet-20241022
|
|
122
|
+
debug: true
|
|
123
|
+
on:
|
|
124
|
+
- manual
|
|
125
|
+
|
|
126
|
+
# Check 2: Code quality review using custom tools
|
|
127
|
+
code-quality:
|
|
128
|
+
type: ai
|
|
129
|
+
prompt: |
|
|
130
|
+
You are a code quality reviewer. You have specialized analysis tools.
|
|
131
|
+
|
|
132
|
+
Tasks:
|
|
133
|
+
1. Use 'count-todos' to get an overview of pending work
|
|
134
|
+
2. Use 'git-recent-changes' to understand recent activity
|
|
135
|
+
3. Use 'grep-pattern' to find console.log statements that should be removed
|
|
136
|
+
|
|
137
|
+
Provide recommendations for improving code quality.
|
|
138
|
+
ai_custom_tools:
|
|
139
|
+
- count-todos
|
|
140
|
+
- git-recent-changes
|
|
141
|
+
- grep-pattern
|
|
142
|
+
ai:
|
|
143
|
+
provider: anthropic
|
|
144
|
+
model: claude-3-5-sonnet-20241022
|
|
145
|
+
on:
|
|
146
|
+
- manual
|
|
147
|
+
|
|
148
|
+
# Check 3: File-specific analysis
|
|
149
|
+
analyze-file:
|
|
150
|
+
type: ai
|
|
151
|
+
prompt: |
|
|
152
|
+
You are analyzing a specific file in the codebase.
|
|
153
|
+
|
|
154
|
+
Use the 'file-stats' tool to get information about: src/index.ts
|
|
155
|
+
Then use 'grep-pattern' to find all exported functions in that file.
|
|
156
|
+
|
|
157
|
+
Provide a summary of what this file does based on your analysis.
|
|
158
|
+
ai_custom_tools:
|
|
159
|
+
- file-stats
|
|
160
|
+
- grep-pattern
|
|
161
|
+
ai:
|
|
162
|
+
provider: anthropic
|
|
163
|
+
model: claude-3-5-sonnet-20241022
|
|
164
|
+
on:
|
|
165
|
+
- manual
|
|
166
|
+
|
|
167
|
+
# Check 4: Comprehensive review combining custom tools and MCP servers
|
|
168
|
+
comprehensive-review:
|
|
169
|
+
type: ai
|
|
170
|
+
prompt: |
|
|
171
|
+
You are performing a comprehensive code review with access to multiple tools.
|
|
172
|
+
|
|
173
|
+
Custom tools available:
|
|
174
|
+
- check-secrets: Scan for hardcoded secrets
|
|
175
|
+
- count-todos: Count pending work items
|
|
176
|
+
- grep-pattern: Search for patterns
|
|
177
|
+
- git-recent-changes: See recent commits
|
|
178
|
+
- file-stats: Get file information
|
|
179
|
+
|
|
180
|
+
Use these tools strategically to provide a thorough review of the codebase.
|
|
181
|
+
Focus on security, code quality, and technical debt.
|
|
182
|
+
ai_custom_tools:
|
|
183
|
+
- check-secrets
|
|
184
|
+
- count-todos
|
|
185
|
+
- grep-pattern
|
|
186
|
+
- git-recent-changes
|
|
187
|
+
- file-stats
|
|
188
|
+
ai_mcp_servers:
|
|
189
|
+
# You can combine custom tools with external MCP servers
|
|
190
|
+
filesystem:
|
|
191
|
+
command: npx
|
|
192
|
+
args: ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/workspace"]
|
|
193
|
+
ai:
|
|
194
|
+
provider: anthropic
|
|
195
|
+
model: claude-3-5-sonnet-20241022
|
|
196
|
+
debug: true
|
|
197
|
+
on:
|
|
198
|
+
- manual
|
|
199
|
+
|
|
200
|
+
# Output configuration
|
|
201
|
+
output:
|
|
202
|
+
pr_comment:
|
|
203
|
+
enabled: true
|
|
204
|
+
format: markdown
|
|
205
|
+
group_by: check
|
|
206
|
+
collapse: false
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
version: "1.0"
|
|
2
|
+
|
|
3
|
+
# Example: Using Custom Tools with AI (Reusing ai_mcp_servers)
|
|
4
|
+
# This shows the PREFERRED way to expose custom tools - no new config section needed!
|
|
5
|
+
|
|
6
|
+
# Define custom tools
|
|
7
|
+
tools:
|
|
8
|
+
grep-pattern:
|
|
9
|
+
name: grep-pattern
|
|
10
|
+
description: Search for specific patterns in TypeScript files
|
|
11
|
+
inputSchema:
|
|
12
|
+
type: object
|
|
13
|
+
properties:
|
|
14
|
+
pattern:
|
|
15
|
+
type: string
|
|
16
|
+
description: The pattern to search for (regex supported)
|
|
17
|
+
required: [pattern]
|
|
18
|
+
exec: 'grep -rn "{{ args.pattern }}" *.ts 2>/dev/null || echo "No matches"'
|
|
19
|
+
parseJson: false
|
|
20
|
+
|
|
21
|
+
check-secrets:
|
|
22
|
+
name: check-secrets
|
|
23
|
+
description: Scan for hardcoded secrets and API keys
|
|
24
|
+
inputSchema:
|
|
25
|
+
type: object
|
|
26
|
+
properties: {}
|
|
27
|
+
exec: |
|
|
28
|
+
grep -rn -E "(api[_-]?key|secret|password|token)\s*[:=]" . 2>/dev/null | head -10 || echo "No secrets found"
|
|
29
|
+
parseJson: false
|
|
30
|
+
|
|
31
|
+
count-todos:
|
|
32
|
+
name: count-todos
|
|
33
|
+
description: Count TODO comments in the codebase
|
|
34
|
+
inputSchema:
|
|
35
|
+
type: object
|
|
36
|
+
properties: {}
|
|
37
|
+
exec: 'grep -r "TODO" src/ 2>/dev/null | wc -l'
|
|
38
|
+
parseJson: false
|
|
39
|
+
|
|
40
|
+
steps:
|
|
41
|
+
# PREFERRED: Use "tools:" in ai_mcp_servers
|
|
42
|
+
security-review:
|
|
43
|
+
type: ai
|
|
44
|
+
prompt: |
|
|
45
|
+
You have access to custom security scanning tools.
|
|
46
|
+
Use check-secrets to scan for hardcoded credentials.
|
|
47
|
+
Use grep-pattern to find dangerous function calls.
|
|
48
|
+
ai_mcp_servers:
|
|
49
|
+
# Use "tools:" to reference custom tools - they'll be served via ephemeral SSE!
|
|
50
|
+
custom-tools:
|
|
51
|
+
tools: [check-secrets, grep-pattern] # ← Magic happens here!
|
|
52
|
+
# You can still combine with external MCP servers
|
|
53
|
+
filesystem:
|
|
54
|
+
command: npx
|
|
55
|
+
args: ["-y", "@modelcontextprotocol/server-filesystem", "."]
|
|
56
|
+
ai:
|
|
57
|
+
provider: anthropic
|
|
58
|
+
model: claude-3-5-sonnet-20241022
|
|
59
|
+
debug: true
|
|
60
|
+
|
|
61
|
+
# ALSO WORKS: Legacy ai_custom_tools format (for backward compatibility)
|
|
62
|
+
code-quality:
|
|
63
|
+
type: ai
|
|
64
|
+
prompt: |
|
|
65
|
+
Use count-todos to analyze pending work items.
|
|
66
|
+
ai_custom_tools: [count-todos] # ← Also works, but ai_mcp_servers is preferred
|
|
67
|
+
ai:
|
|
68
|
+
provider: anthropic
|
|
69
|
+
model: claude-3-5-sonnet-20241022
|
|
70
|
+
|
|
71
|
+
output:
|
|
72
|
+
pr_comment:
|
|
73
|
+
enabled: true
|
|
74
|
+
format: markdown
|
|
75
|
+
group_by: check
|
|
76
|
+
collapse: false
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Basic Git Checkout Example
|
|
2
|
+
#
|
|
3
|
+
# This example demonstrates a simple workflow that:
|
|
4
|
+
# 1. Checks out the PR head branch
|
|
5
|
+
# 2. Runs tests
|
|
6
|
+
# 3. Builds the project
|
|
7
|
+
|
|
8
|
+
version: "1.0"
|
|
9
|
+
|
|
10
|
+
steps:
|
|
11
|
+
# Checkout the PR head branch
|
|
12
|
+
checkout:
|
|
13
|
+
type: git-checkout
|
|
14
|
+
ref: "{{ pr.head }}"
|
|
15
|
+
criticality: internal
|
|
16
|
+
|
|
17
|
+
# Run tests on the checked out code
|
|
18
|
+
test:
|
|
19
|
+
type: command
|
|
20
|
+
depends_on: [checkout]
|
|
21
|
+
exec: npm test
|
|
22
|
+
working_directory: "{{ outputs.checkout.path }}"
|
|
23
|
+
assume: "outputs.checkout.success"
|
|
24
|
+
criticality: internal
|
|
25
|
+
|
|
26
|
+
# Build the project
|
|
27
|
+
build:
|
|
28
|
+
type: command
|
|
29
|
+
depends_on: [test]
|
|
30
|
+
exec: npm run build
|
|
31
|
+
working_directory: "{{ outputs.checkout.path }}"
|
|
32
|
+
criticality: internal
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Git Checkout Compare Example
|
|
2
|
+
#
|
|
3
|
+
# This example demonstrates checking out multiple branches
|
|
4
|
+
# and comparing them.
|
|
5
|
+
|
|
6
|
+
version: "1.0"
|
|
7
|
+
|
|
8
|
+
# Configure worktree cache
|
|
9
|
+
worktree_cache:
|
|
10
|
+
enabled: true
|
|
11
|
+
base_path: /tmp/visor-compare
|
|
12
|
+
cleanup_on_exit: true
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
# Checkout PR head branch
|
|
16
|
+
checkout-head:
|
|
17
|
+
type: git-checkout
|
|
18
|
+
ref: "{{ pr.head }}"
|
|
19
|
+
criticality: internal
|
|
20
|
+
|
|
21
|
+
# Checkout PR base branch
|
|
22
|
+
checkout-base:
|
|
23
|
+
type: git-checkout
|
|
24
|
+
ref: "{{ pr.base }}"
|
|
25
|
+
criticality: internal
|
|
26
|
+
|
|
27
|
+
# Run tests on head branch
|
|
28
|
+
test-head:
|
|
29
|
+
type: command
|
|
30
|
+
depends_on: [checkout-head]
|
|
31
|
+
exec: npm test
|
|
32
|
+
working_directory: "{{ outputs['checkout-head'].path }}"
|
|
33
|
+
continue_on_failure: true
|
|
34
|
+
criticality: internal
|
|
35
|
+
|
|
36
|
+
# Run tests on base branch
|
|
37
|
+
test-base:
|
|
38
|
+
type: command
|
|
39
|
+
depends_on: [checkout-base]
|
|
40
|
+
exec: npm test
|
|
41
|
+
working_directory: "{{ outputs['checkout-base'].path }}"
|
|
42
|
+
continue_on_failure: true
|
|
43
|
+
criticality: internal
|
|
44
|
+
|
|
45
|
+
# Compare results
|
|
46
|
+
compare:
|
|
47
|
+
type: command
|
|
48
|
+
depends_on: [test-head, test-base]
|
|
49
|
+
exec: |
|
|
50
|
+
echo "=== Comparison Results ==="
|
|
51
|
+
echo "Head branch: {{ pr.head }} ({{ outputs['checkout-head'].commit }})"
|
|
52
|
+
echo "Base branch: {{ pr.base }} ({{ outputs['checkout-base'].commit }})"
|
|
53
|
+
echo ""
|
|
54
|
+
echo "Head tests: {{ outputs['test-head'].exitCode == 0 ? 'PASSED' : 'FAILED' }}"
|
|
55
|
+
echo "Base tests: {{ outputs['test-base'].exitCode == 0 ? 'PASSED' : 'FAILED' }}"
|
|
56
|
+
echo ""
|
|
57
|
+
echo "File differences:"
|
|
58
|
+
diff -r "{{ outputs['checkout-head'].path }}/src" "{{ outputs['checkout-base'].path }}/src" || true
|
|
59
|
+
criticality: info
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Cross-Repository Checkout Example
|
|
2
|
+
#
|
|
3
|
+
# This example demonstrates checking out multiple repositories
|
|
4
|
+
# and running integration tests.
|
|
5
|
+
|
|
6
|
+
version: "1.0"
|
|
7
|
+
|
|
8
|
+
steps:
|
|
9
|
+
# Checkout main application repository
|
|
10
|
+
checkout-app:
|
|
11
|
+
type: git-checkout
|
|
12
|
+
repository: myorg/main-app
|
|
13
|
+
ref: "{{ pr.head }}"
|
|
14
|
+
token: "{{ env.GITHUB_TOKEN }}"
|
|
15
|
+
criticality: internal
|
|
16
|
+
|
|
17
|
+
# Checkout shared library repository
|
|
18
|
+
checkout-lib:
|
|
19
|
+
type: git-checkout
|
|
20
|
+
repository: myorg/shared-lib
|
|
21
|
+
ref: main
|
|
22
|
+
token: "{{ env.GITHUB_TOKEN }}"
|
|
23
|
+
criticality: internal
|
|
24
|
+
|
|
25
|
+
# Checkout test utilities repository
|
|
26
|
+
checkout-test-utils:
|
|
27
|
+
type: git-checkout
|
|
28
|
+
repository: myorg/test-utils
|
|
29
|
+
ref: v2.0.0
|
|
30
|
+
token: "{{ env.GITHUB_TOKEN }}"
|
|
31
|
+
criticality: internal
|
|
32
|
+
|
|
33
|
+
# Install dependencies in all repositories
|
|
34
|
+
install-deps:
|
|
35
|
+
type: command
|
|
36
|
+
depends_on: [checkout-app, checkout-lib, checkout-test-utils]
|
|
37
|
+
exec: |
|
|
38
|
+
echo "Installing dependencies for main app..."
|
|
39
|
+
cd "{{ outputs['checkout-app'].path }}" && npm install
|
|
40
|
+
|
|
41
|
+
echo "Installing dependencies for shared lib..."
|
|
42
|
+
cd "{{ outputs['checkout-lib'].path }}" && npm install
|
|
43
|
+
|
|
44
|
+
echo "Installing dependencies for test utils..."
|
|
45
|
+
cd "{{ outputs['checkout-test-utils'].path }}" && npm install
|
|
46
|
+
criticality: internal
|
|
47
|
+
|
|
48
|
+
# Run integration tests
|
|
49
|
+
integration-test:
|
|
50
|
+
type: command
|
|
51
|
+
depends_on: [install-deps]
|
|
52
|
+
exec: |
|
|
53
|
+
export LIB_PATH="{{ outputs['checkout-lib'].path }}"
|
|
54
|
+
export TEST_UTILS_PATH="{{ outputs['checkout-test-utils'].path }}"
|
|
55
|
+
npm run test:integration
|
|
56
|
+
working_directory: "{{ outputs['checkout-app'].path }}"
|
|
57
|
+
criticality: internal
|
|
58
|
+
|
|
59
|
+
# Generate integration report
|
|
60
|
+
report:
|
|
61
|
+
type: command
|
|
62
|
+
depends_on: [integration-test]
|
|
63
|
+
exec: |
|
|
64
|
+
cat << EOF
|
|
65
|
+
# Integration Test Report
|
|
66
|
+
|
|
67
|
+
## Repositories Tested
|
|
68
|
+
- **Main App**: {{ outputs['checkout-app'].repository }}@{{ outputs['checkout-app'].commit }}
|
|
69
|
+
- **Shared Lib**: {{ outputs['checkout-lib'].repository }}@{{ outputs['checkout-lib'].commit }}
|
|
70
|
+
- **Test Utils**: {{ outputs['checkout-test-utils'].repository }}@{{ outputs['checkout-test-utils'].commit }}
|
|
71
|
+
|
|
72
|
+
## Test Results
|
|
73
|
+
Exit Code: {{ outputs['integration-test'].exitCode }}
|
|
74
|
+
Status: {{ outputs['integration-test'].exitCode == 0 ? 'PASSED ✅' : 'FAILED ❌' }}
|
|
75
|
+
EOF
|
|
76
|
+
criticality: info
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
version: "1.0"
|
|
2
|
+
|
|
3
|
+
# Example: Using Imported Reusable Tools and Workflows with on_init
|
|
4
|
+
# This demonstrates how to import tools and workflows from separate files
|
|
5
|
+
# and use them multiple times in on_init hooks.
|
|
6
|
+
#
|
|
7
|
+
# NOTE: In production, you would use extends to import from separate files:
|
|
8
|
+
#
|
|
9
|
+
# extends:
|
|
10
|
+
# - ./reusable-tools.yaml
|
|
11
|
+
# - ./reusable-workflows.yaml
|
|
12
|
+
#
|
|
13
|
+
# For test compatibility, tools and workflows are shown inline below (commented out).
|
|
14
|
+
|
|
15
|
+
# NOTE: Reusable tools would be imported from reusable-tools.yaml
|
|
16
|
+
# In production, those tools would be available after extends.
|
|
17
|
+
# tools:
|
|
18
|
+
# fetch-jira-issue:
|
|
19
|
+
# exec: |
|
|
20
|
+
# echo '{"key":"PROJ-456","summary":"Example issue",...}'
|
|
21
|
+
# parseJson: true
|
|
22
|
+
# fetch-external-data:
|
|
23
|
+
# exec: |
|
|
24
|
+
# case {{ args.source }} in
|
|
25
|
+
# user-db) echo '{"source":"user-db","data":{"count":2}}' ;;
|
|
26
|
+
# metrics-api) echo '{"source":"metrics-api","data":{"cpu":45}}' ;;
|
|
27
|
+
# esac
|
|
28
|
+
# parseJson: true
|
|
29
|
+
|
|
30
|
+
# NOTE: Reusable workflows would be imported from reusable-workflows.yaml
|
|
31
|
+
# workflows:
|
|
32
|
+
# data-enrichment:
|
|
33
|
+
# steps:
|
|
34
|
+
# - id: fetch-primary
|
|
35
|
+
# exec: echo '{"primary":"data"}'
|
|
36
|
+
# - id: merge-results
|
|
37
|
+
# exec: echo '{"enriched":true}'
|
|
38
|
+
# output_mapping:
|
|
39
|
+
# enriched_data: "{{ outputs['merge-results'] }}"
|
|
40
|
+
|
|
41
|
+
steps:
|
|
42
|
+
# Example 1: Use multiple imported tools in on_init
|
|
43
|
+
# In production: Uses fetch-jira-issue and fetch-external-data from reusable-tools.yaml
|
|
44
|
+
multi-tool-preprocessing:
|
|
45
|
+
type: command
|
|
46
|
+
on_init:
|
|
47
|
+
run:
|
|
48
|
+
- tool: fetch-jira-issue
|
|
49
|
+
with:
|
|
50
|
+
issue_key: PROJ-456
|
|
51
|
+
as: jira-data
|
|
52
|
+
- tool: fetch-external-data
|
|
53
|
+
with:
|
|
54
|
+
source: user-db
|
|
55
|
+
as: user-data
|
|
56
|
+
- tool: fetch-external-data
|
|
57
|
+
with:
|
|
58
|
+
source: metrics-api
|
|
59
|
+
as: metrics-data
|
|
60
|
+
exec: |
|
|
61
|
+
echo "JIRA: {{ outputs['jira-data'].summary }}"
|
|
62
|
+
echo "Users: {{ outputs['user-data'].data.count }}"
|
|
63
|
+
echo "Metrics: {{ outputs['metrics-data'].data.cpu }}%"
|
|
64
|
+
|
|
65
|
+
# Example 2: Use imported workflow in on_init
|
|
66
|
+
# In production: Uses data-enrichment workflow from reusable-workflows.yaml
|
|
67
|
+
workflow-preprocessing:
|
|
68
|
+
type: command
|
|
69
|
+
on_init:
|
|
70
|
+
run:
|
|
71
|
+
- workflow: data-enrichment
|
|
72
|
+
as: enriched
|
|
73
|
+
exec: |
|
|
74
|
+
echo "Enriched: {{ outputs.enriched.enriched_data.enriched }}"
|
|
75
|
+
|
|
76
|
+
# Example 3: Chain imported tools and workflows
|
|
77
|
+
# In production: Uses tools and workflows from imported files
|
|
78
|
+
chain-tools-and-workflows:
|
|
79
|
+
type: command
|
|
80
|
+
on_init:
|
|
81
|
+
run:
|
|
82
|
+
- tool: fetch-external-data
|
|
83
|
+
with:
|
|
84
|
+
source: config-service
|
|
85
|
+
as: config
|
|
86
|
+
- workflow: multi-step-validation
|
|
87
|
+
as: validation
|
|
88
|
+
- tool: validate-data
|
|
89
|
+
with:
|
|
90
|
+
data: "{{ outputs.config.data }}"
|
|
91
|
+
as: final-check
|
|
92
|
+
exec: |
|
|
93
|
+
echo "Config: {{ outputs.config.data.version }}"
|
|
94
|
+
echo "Validation: {{ outputs.validation.validation_result.status }}"
|
|
95
|
+
echo "Final: {{ outputs['final-check'].valid }}"
|
|
96
|
+
|
|
97
|
+
# Example 4: Use same tool multiple times with different parameters
|
|
98
|
+
# Demonstrates tool reusability across multiple invocations
|
|
99
|
+
repeated-tool-usage:
|
|
100
|
+
type: command
|
|
101
|
+
on_init:
|
|
102
|
+
run:
|
|
103
|
+
- tool: fetch-external-data
|
|
104
|
+
with:
|
|
105
|
+
source: user-db
|
|
106
|
+
as: users
|
|
107
|
+
- tool: fetch-external-data
|
|
108
|
+
with:
|
|
109
|
+
source: config-service
|
|
110
|
+
as: config
|
|
111
|
+
- tool: fetch-external-data
|
|
112
|
+
with:
|
|
113
|
+
source: metrics-api
|
|
114
|
+
as: metrics
|
|
115
|
+
exec: |
|
|
116
|
+
echo "Fetched from 3 sources:"
|
|
117
|
+
echo "- {{ outputs.users.source }}: {{ outputs.users.data.count }} users"
|
|
118
|
+
echo "- {{ outputs.config.source }}: version {{ outputs.config.data.version }}"
|
|
119
|
+
echo "- {{ outputs.metrics.source }}: {{ outputs.metrics.data.cpu }}% CPU"
|
|
120
|
+
|
|
121
|
+
tests:
|
|
122
|
+
defaults:
|
|
123
|
+
strict: false
|
|
124
|
+
fail_on_unexpected_calls: false
|
|
125
|
+
fixtures: []
|
|
126
|
+
cases:
|
|
127
|
+
- name: multi-tool-preprocessing-test
|
|
128
|
+
description: Test using multiple imported tools in on_init
|
|
129
|
+
event: manual
|
|
130
|
+
fixture: gh.pr_open.minimal
|
|
131
|
+
mocks:
|
|
132
|
+
multi-tool-preprocessing: |
|
|
133
|
+
JIRA: Example issue
|
|
134
|
+
Users: 2
|
|
135
|
+
Metrics: 45%
|
|
136
|
+
expect:
|
|
137
|
+
calls:
|
|
138
|
+
- step: multi-tool-preprocessing
|
|
139
|
+
exactly: 1
|
|
140
|
+
|
|
141
|
+
- name: workflow-preprocessing-test
|
|
142
|
+
description: Test using imported workflow in on_init
|
|
143
|
+
event: manual
|
|
144
|
+
fixture: gh.pr_open.minimal
|
|
145
|
+
mocks:
|
|
146
|
+
workflow-preprocessing: "Enriched: true"
|
|
147
|
+
expect:
|
|
148
|
+
calls:
|
|
149
|
+
- step: workflow-preprocessing
|
|
150
|
+
exactly: 1
|
|
151
|
+
|
|
152
|
+
- name: chain-tools-workflows-test
|
|
153
|
+
description: Test chaining imported tools and workflows
|
|
154
|
+
event: manual
|
|
155
|
+
fixture: gh.pr_open.minimal
|
|
156
|
+
mocks:
|
|
157
|
+
chain-tools-and-workflows: |
|
|
158
|
+
Config: 1.2.3
|
|
159
|
+
Validation: approved
|
|
160
|
+
Final: true
|
|
161
|
+
expect:
|
|
162
|
+
calls:
|
|
163
|
+
- step: chain-tools-and-workflows
|
|
164
|
+
exactly: 1
|
|
165
|
+
|
|
166
|
+
- name: repeated-tool-test
|
|
167
|
+
description: Test using same tool multiple times
|
|
168
|
+
event: manual
|
|
169
|
+
fixture: gh.pr_open.minimal
|
|
170
|
+
mocks:
|
|
171
|
+
repeated-tool-usage: |
|
|
172
|
+
Fetched from 3 sources:
|
|
173
|
+
- user-db: 2 users
|
|
174
|
+
- config-service: version 1.2.3
|
|
175
|
+
- metrics-api: 45% CPU
|
|
176
|
+
expect:
|
|
177
|
+
calls:
|
|
178
|
+
- step: repeated-tool-usage
|
|
179
|
+
exactly: 1
|