@probelabs/visor 0.1.149 → 0.1.150-ee

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 (131) hide show
  1. package/README.md +52 -1
  2. package/dist/909.index.js +27117 -0
  3. package/dist/ai-review-service.d.ts.map +1 -1
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/docs/assistant-workflows.md +805 -0
  6. package/dist/docs/event-triggers.md +25 -0
  7. package/dist/docs/scheduler.md +156 -0
  8. package/dist/docs/slack-integration.md +48 -0
  9. package/dist/enterprise/scheduler/knex-store.d.ts +7 -1
  10. package/dist/enterprise/scheduler/knex-store.d.ts.map +1 -1
  11. package/dist/examples/code-talk-as-tool.yaml +76 -0
  12. package/dist/examples/code-talk-workflow.yaml +68 -0
  13. package/dist/examples/intent-router-workflow.yaml +66 -0
  14. package/dist/examples/slack-message-triggers.yaml +270 -0
  15. package/dist/generated/config-schema.d.ts +102 -7
  16. package/dist/generated/config-schema.d.ts.map +1 -1
  17. package/dist/generated/config-schema.json +116 -7
  18. package/dist/git-repository-analyzer.d.ts +8 -0
  19. package/dist/git-repository-analyzer.d.ts.map +1 -1
  20. package/dist/index.js +5868 -4756
  21. package/dist/scheduler/message-trigger.d.ts +47 -0
  22. package/dist/scheduler/message-trigger.d.ts.map +1 -0
  23. package/dist/scheduler/schedule-store.d.ts +31 -1
  24. package/dist/scheduler/schedule-store.d.ts.map +1 -1
  25. package/dist/scheduler/schedule-tool.d.ts +17 -1
  26. package/dist/scheduler/schedule-tool.d.ts.map +1 -1
  27. package/dist/scheduler/store/sqlite-store.d.ts +7 -1
  28. package/dist/scheduler/store/sqlite-store.d.ts.map +1 -1
  29. package/dist/scheduler/store/types.d.ts +45 -0
  30. package/dist/scheduler/store/types.d.ts.map +1 -1
  31. package/dist/sdk/{check-provider-registry-LVLC4EPF.mjs → check-provider-registry-RRYBG6AU.mjs} +6 -6
  32. package/dist/sdk/{check-provider-registry-X4OZJWPK.mjs → check-provider-registry-VHM53BTI.mjs} +6 -6
  33. package/dist/sdk/{chunk-V6GI4U2M.mjs → chunk-AADKUA6L.mjs} +585 -29
  34. package/dist/sdk/{chunk-6EXCUX7Y.mjs.map → chunk-AADKUA6L.mjs.map} +1 -1
  35. package/dist/sdk/{chunk-YYZAN5NK.mjs → chunk-FYK2DJK6.mjs} +106 -9
  36. package/dist/sdk/chunk-FYK2DJK6.mjs.map +1 -0
  37. package/dist/sdk/{chunk-RJLJUTSU.mjs → chunk-FZEQ744M.mjs} +2 -2
  38. package/dist/sdk/{chunk-Q6EPAJ6Z.mjs → chunk-GLROSEYJ.mjs} +3 -3
  39. package/dist/sdk/{chunk-6EXCUX7Y.mjs → chunk-O4H5KZ7Y.mjs} +586 -30
  40. package/dist/sdk/{chunk-GFNXX64M.mjs.map → chunk-O4H5KZ7Y.mjs.map} +1 -1
  41. package/dist/sdk/{chunk-62TNF5PJ.mjs → chunk-PETLPNRA.mjs} +2 -2
  42. package/dist/sdk/{chunk-62TNF5PJ.mjs.map → chunk-PETLPNRA.mjs.map} +1 -1
  43. package/dist/sdk/{config-KQH254CA.mjs → config-MTEIGCOQ.mjs} +2 -2
  44. package/dist/sdk/{failure-condition-evaluator-IVCTD4BZ.mjs → failure-condition-evaluator-XV2ZMFFY.mjs} +3 -3
  45. package/dist/sdk/{git-repository-analyzer-QFMW6WIS.mjs → git-repository-analyzer-TWNJUN42.mjs} +34 -3
  46. package/dist/sdk/git-repository-analyzer-TWNJUN42.mjs.map +1 -0
  47. package/dist/sdk/{github-frontend-DFT5G32K.mjs → github-frontend-A2R7D4N6.mjs} +3 -3
  48. package/dist/sdk/{host-7YKRMOUJ.mjs → host-BRZQLVCH.mjs} +2 -2
  49. package/dist/sdk/{host-H7IX4GBK.mjs → host-MR7L57QI.mjs} +2 -2
  50. package/dist/sdk/knex-store-CRORFJE6.mjs +527 -0
  51. package/dist/sdk/knex-store-CRORFJE6.mjs.map +1 -0
  52. package/dist/sdk/loader-NJCF7DUS.mjs +89 -0
  53. package/dist/sdk/loader-NJCF7DUS.mjs.map +1 -0
  54. package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs +655 -0
  55. package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs.map +1 -0
  56. package/dist/sdk/{routing-LU5PAREW.mjs → routing-V3MYZAOH.mjs} +4 -4
  57. package/dist/sdk/{schedule-tool-EOMZFICZ.mjs → schedule-tool-4QDBJV74.mjs} +6 -6
  58. package/dist/sdk/{schedule-tool-NX75VKGA.mjs → schedule-tool-NYLNJUEW.mjs} +6 -6
  59. package/dist/sdk/{schedule-tool-handler-3FJHDIPG.mjs → schedule-tool-handler-27XEVLSY.mjs} +6 -6
  60. package/dist/sdk/{schedule-tool-handler-KKN7XJYT.mjs → schedule-tool-handler-EFQIYD3W.mjs} +6 -6
  61. package/dist/sdk/sdk.d.mts +38 -1
  62. package/dist/sdk/sdk.d.ts +38 -1
  63. package/dist/sdk/sdk.js +2338 -280
  64. package/dist/sdk/sdk.js.map +1 -1
  65. package/dist/sdk/sdk.mjs +5 -5
  66. package/dist/sdk/{trace-helpers-EJUIOP6L.mjs → trace-helpers-6NSZBC35.mjs} +2 -2
  67. package/dist/sdk/validator-XTZJZZJH.mjs +134 -0
  68. package/dist/sdk/validator-XTZJZZJH.mjs.map +1 -0
  69. package/dist/sdk/{workflow-check-provider-AGZ5JY2I.mjs → workflow-check-provider-3MVUCEJR.mjs} +6 -6
  70. package/dist/sdk/{workflow-check-provider-PTNUWM5W.mjs → workflow-check-provider-XLH7N4FV.mjs} +6 -6
  71. package/dist/slack/socket-runner.d.ts +14 -0
  72. package/dist/slack/socket-runner.d.ts.map +1 -1
  73. package/dist/test-runner/core/flow-stage.d.ts.map +1 -1
  74. package/dist/test-runner/fixture-loader.d.ts +1 -1
  75. package/dist/test-runner/fixture-loader.d.ts.map +1 -1
  76. package/dist/test-runner/index.d.ts.map +1 -1
  77. package/dist/test-runner/validator.d.ts.map +1 -1
  78. package/dist/types/config.d.ts +38 -1
  79. package/dist/types/config.d.ts.map +1 -1
  80. package/dist/utils/workspace-manager.d.ts +4 -0
  81. package/dist/utils/workspace-manager.d.ts.map +1 -1
  82. package/dist/utils/worktree-manager.d.ts +15 -1
  83. package/dist/utils/worktree-manager.d.ts.map +1 -1
  84. package/package.json +2 -2
  85. package/dist/output/traces/run-2026-03-03T07-19-07-543Z.ndjson +0 -138
  86. package/dist/output/traces/run-2026-03-03T07-19-50-933Z.ndjson +0 -2121
  87. package/dist/sdk/check-provider-registry-IYSUDKPB.mjs +0 -29
  88. package/dist/sdk/chunk-BR7DYA3S.mjs +0 -739
  89. package/dist/sdk/chunk-CISJ6DJW.mjs +0 -1502
  90. package/dist/sdk/chunk-GFNXX64M.mjs +0 -43159
  91. package/dist/sdk/chunk-Q6EPAJ6Z.mjs.map +0 -1
  92. package/dist/sdk/chunk-RJLJUTSU.mjs.map +0 -1
  93. package/dist/sdk/chunk-V6GI4U2M.mjs.map +0 -1
  94. package/dist/sdk/chunk-VLUGLWLA.mjs +0 -443
  95. package/dist/sdk/chunk-VLUGLWLA.mjs.map +0 -1
  96. package/dist/sdk/chunk-YYZAN5NK.mjs.map +0 -1
  97. package/dist/sdk/failure-condition-evaluator-LZ2AG5PY.mjs +0 -17
  98. package/dist/sdk/git-repository-analyzer-QFMW6WIS.mjs.map +0 -1
  99. package/dist/sdk/github-frontend-S523EEJB.mjs +0 -1368
  100. package/dist/sdk/github-frontend-S523EEJB.mjs.map +0 -1
  101. package/dist/sdk/routing-ZMBKWMVI.mjs +0 -25
  102. package/dist/sdk/schedule-tool-CDVUSZEG.mjs +0 -35
  103. package/dist/sdk/schedule-tool-handler-KKN7XJYT.mjs.map +0 -1
  104. package/dist/sdk/schedule-tool-handler-QNZG55DX.mjs +0 -39
  105. package/dist/sdk/schedule-tool-handler-QNZG55DX.mjs.map +0 -1
  106. package/dist/sdk/trace-helpers-6ROJR7N3.mjs +0 -25
  107. package/dist/sdk/trace-helpers-6ROJR7N3.mjs.map +0 -1
  108. package/dist/sdk/trace-helpers-EJUIOP6L.mjs.map +0 -1
  109. package/dist/sdk/workflow-check-provider-6ERNNCNA.mjs +0 -29
  110. package/dist/sdk/workflow-check-provider-6ERNNCNA.mjs.map +0 -1
  111. package/dist/sdk/workflow-check-provider-AGZ5JY2I.mjs.map +0 -1
  112. package/dist/sdk/workflow-check-provider-PTNUWM5W.mjs.map +0 -1
  113. package/dist/traces/run-2026-03-03T07-19-07-543Z.ndjson +0 -138
  114. package/dist/traces/run-2026-03-03T07-19-50-933Z.ndjson +0 -2121
  115. /package/dist/sdk/{check-provider-registry-IYSUDKPB.mjs.map → check-provider-registry-RRYBG6AU.mjs.map} +0 -0
  116. /package/dist/sdk/{check-provider-registry-LVLC4EPF.mjs.map → check-provider-registry-VHM53BTI.mjs.map} +0 -0
  117. /package/dist/sdk/{chunk-BR7DYA3S.mjs.map → chunk-FZEQ744M.mjs.map} +0 -0
  118. /package/dist/sdk/{chunk-CISJ6DJW.mjs.map → chunk-GLROSEYJ.mjs.map} +0 -0
  119. /package/dist/sdk/{check-provider-registry-X4OZJWPK.mjs.map → config-MTEIGCOQ.mjs.map} +0 -0
  120. /package/dist/sdk/{config-KQH254CA.mjs.map → failure-condition-evaluator-XV2ZMFFY.mjs.map} +0 -0
  121. /package/dist/sdk/{github-frontend-DFT5G32K.mjs.map → github-frontend-A2R7D4N6.mjs.map} +0 -0
  122. /package/dist/sdk/{host-7YKRMOUJ.mjs.map → host-BRZQLVCH.mjs.map} +0 -0
  123. /package/dist/sdk/{host-H7IX4GBK.mjs.map → host-MR7L57QI.mjs.map} +0 -0
  124. /package/dist/sdk/{failure-condition-evaluator-IVCTD4BZ.mjs.map → routing-V3MYZAOH.mjs.map} +0 -0
  125. /package/dist/sdk/{failure-condition-evaluator-LZ2AG5PY.mjs.map → schedule-tool-4QDBJV74.mjs.map} +0 -0
  126. /package/dist/sdk/{routing-LU5PAREW.mjs.map → schedule-tool-NYLNJUEW.mjs.map} +0 -0
  127. /package/dist/sdk/{routing-ZMBKWMVI.mjs.map → schedule-tool-handler-27XEVLSY.mjs.map} +0 -0
  128. /package/dist/sdk/{schedule-tool-CDVUSZEG.mjs.map → schedule-tool-handler-EFQIYD3W.mjs.map} +0 -0
  129. /package/dist/sdk/{schedule-tool-EOMZFICZ.mjs.map → trace-helpers-6NSZBC35.mjs.map} +0 -0
  130. /package/dist/sdk/{schedule-tool-NX75VKGA.mjs.map → workflow-check-provider-3MVUCEJR.mjs.map} +0 -0
  131. /package/dist/sdk/{schedule-tool-handler-3FJHDIPG.mjs.map → workflow-check-provider-XLH7N4FV.mjs.map} +0 -0
@@ -185,6 +185,29 @@ The complete list of event triggers that can be used in the `on` field:
185
185
  | `manual` | Manual CLI invocation |
186
186
  | `schedule` | Scheduled execution (cron or workflow_dispatch) |
187
187
  | `webhook_received` | HTTP webhook was received (via http_input provider) |
188
+ | `slack_message` | Slack message matched an `on_message` trigger (see [Scheduler - Message Triggers](./scheduler.md#message-triggers-on_message)) |
189
+
190
+ ### Slack Message Trigger Events (`slack_message`)
191
+
192
+ When a Slack message matches a configured `on_message` trigger (defined in `scheduler.on_message`), the specified workflow is dispatched with event type `slack_message`. This allows reactive workflows based on message content in specific channels, without requiring an @mention.
193
+
194
+ - **Trigger mapping**: `slack_message`
195
+ - **Source**: `scheduler.on_message` filter match in Slack Socket Mode
196
+ - **Log format**:
197
+ ```
198
+ [SlackSocket] Message trigger 'cicd-watcher' matched → workflow="handle-cicd" channel=C0CICD ts=1700.001
199
+ ```
200
+
201
+ Steps can filter on this event type:
202
+ ```yaml
203
+ steps:
204
+ handle-cicd-failure:
205
+ on: [slack_message] # Only runs when triggered by on_message
206
+ type: ai
207
+ prompt: "Analyze the CI/CD failure."
208
+ ```
209
+
210
+ See [Scheduler - Message Triggers](./scheduler.md#message-triggers-on_message) for configuration details.
188
211
 
189
212
  ## Configuration
190
213
 
@@ -241,6 +264,7 @@ The `goto_event` field accepts any valid `EventTrigger` value:
241
264
  - `pr_opened`, `pr_updated`, `pr_closed`
242
265
  - `issue_opened`, `issue_comment`
243
266
  - `manual`, `schedule`, `webhook_received`
267
+ - `slack_message`
244
268
 
245
269
  For complete documentation on failure routing, retry policies, and loop control, see [Failure Routing](./failure-routing.md).
246
270
 
@@ -300,6 +324,7 @@ visor --check security --event pr_updated
300
324
  | `--event issue_comment` | Only runs checks with `on: [issue_comment]` | Test comment assistant |
301
325
  | `--event manual` | Only runs checks with `on: [manual]` | Test manual-triggered checks |
302
326
  | `--event schedule` | Only runs checks with `on: [schedule]` | Test scheduled/cron checks |
327
+ | `--event slack_message` | Only runs checks with `on: [slack_message]` | Test message trigger workflows |
303
328
  | `--event all` | Runs all checks (except manual-only) | Default behavior, ignores `on:` filters |
304
329
  | (no flag) | Auto-detects based on schema | Smart default |
305
330
 
@@ -63,6 +63,160 @@ scheduler:
63
63
  target: "#platform-team"
64
64
  ```
65
65
 
66
+ ## Message Triggers (`on_message`)
67
+
68
+ Message triggers allow workflows to be executed reactively based on Slack messages, without requiring an @mention. This is useful for monitoring channels (e.g., CI/CD failure notifications) and automatically triggering workflows in response.
69
+
70
+ ### Configuration
71
+
72
+ Add `on_message` alongside `cron` in the `scheduler` section:
73
+
74
+ ```yaml
75
+ scheduler:
76
+ enabled: true
77
+
78
+ on_message:
79
+ cicd-watcher:
80
+ description: "React to CI/CD failure notifications"
81
+ channels: ["C0CICD"] # Channel IDs (wildcard suffix supported, e.g., "CENG*")
82
+ from: ["U123BOT"] # Optional: only from these user IDs
83
+ from_bots: true # Allow bot messages (default: false)
84
+ contains: ["failed", "error"] # Any keyword match, case-insensitive (OR)
85
+ match: "build.*failed" # Regex pattern (optional)
86
+ threads: root_only # root_only | thread_only | any (default: any)
87
+ workflow: handle-cicd-failure
88
+ inputs:
89
+ source: slack
90
+ output:
91
+ type: slack
92
+ enabled: true
93
+
94
+ thread-responder:
95
+ description: "Respond in threads about deployments"
96
+ channels: ["C0DEPLOY"]
97
+ threads: thread_only # Only react to thread replies
98
+ contains: ["help", "stuck"]
99
+ workflow: deploy-help
100
+ ```
101
+
102
+ ### Filter Options
103
+
104
+ | Option | Type | Default | Description |
105
+ |--------|------|---------|-------------|
106
+ | `channels` | string[] | (all) | Channel IDs to monitor. Supports wildcard suffix (e.g., `CENG*`) |
107
+ | `from` | string[] | (all) | Only trigger on messages from these Slack user IDs |
108
+ | `from_bots` | boolean | `false` | Allow bot messages to trigger. When false, bot messages are ignored |
109
+ | `contains` | string[] | (all) | Keyword match — any keyword triggers (case-insensitive, OR logic) |
110
+ | `match` | string | (none) | Regex pattern to match against message text (case-insensitive) |
111
+ | `threads` | string | `any` | Thread scope: `root_only`, `thread_only`, or `any` |
112
+ | `workflow` | string | **(required)** | Workflow/check ID to execute when triggered |
113
+ | `inputs` | object | `{}` | Workflow inputs passed to the execution |
114
+ | `output` | object | (none) | Output destination (`type`, `target`, `thread_id`) |
115
+ | `description` | string | (none) | Description for logging |
116
+ | `enabled` | boolean | `true` | Enable/disable this trigger |
117
+
118
+ ### Filter Logic
119
+
120
+ - All specified filters must pass (**AND** logic between filters)
121
+ - Within `contains`, any keyword match suffices (**OR** logic)
122
+ - Omitted filters are not checked (they match everything)
123
+
124
+ ### Thread Scope
125
+
126
+ | Value | Behavior |
127
+ |-------|----------|
128
+ | `root_only` | Only react to root channel messages (no `thread_ts` or `thread_ts === ts`) |
129
+ | `thread_only` | Only react to thread replies (`thread_ts` exists and differs from `ts`) |
130
+ | `any` | React to both root messages and thread replies (default) |
131
+
132
+ When a triggered message is a thread reply, full thread conversation context is fetched via `SlackAdapter` and passed to the workflow as `slack_conversation`. When the message is a root channel message, only the single message is available.
133
+
134
+ ### Message Flow
135
+
136
+ ```
137
+ Slack WebSocket Event
138
+ → Parse JSON, ACK
139
+ → Filter subtypes (edited, etc.)
140
+ → Filter self-bot messages
141
+ → Filter guests
142
+ → Evaluate message triggers ← NEW
143
+ → For each match: dispatch workflow async
144
+ → Mention gate (existing @mention path)
145
+ → Thread/allowlist/dedup gates
146
+ → Dispatch all checks (existing mention-based path)
147
+ ```
148
+
149
+ Both paths can fire for the same message. A message that matches a trigger AND contains an @mention will dispatch the triggered workflow AND go through the normal mention-based dispatch. Each triggered workflow gets its own engine instance.
150
+
151
+ ### Webhook Context
152
+
153
+ The triggered workflow receives via `webhookData`:
154
+
155
+ | Field | Description |
156
+ |-------|-------------|
157
+ | `event.text` | Message text |
158
+ | `event.user` | Sender user ID |
159
+ | `event.channel` | Channel ID |
160
+ | `event.ts` / `event.thread_ts` | Message timestamps |
161
+ | `trigger.id` | Which trigger matched |
162
+ | `trigger.type` | `on_message` |
163
+ | `slack_conversation` | Full thread context (if thread reply) |
164
+
165
+ The event type is `slack_message`, which can be used in step `on:` filters:
166
+
167
+ ```yaml
168
+ steps:
169
+ handle-cicd-failure:
170
+ type: ai
171
+ on: [slack_message]
172
+ prompt: "Analyze this CI/CD failure and suggest fixes."
173
+ ```
174
+
175
+ ### Deduplication
176
+
177
+ Each trigger match is deduplicated using the key `trigger:${triggerId}:${channel}:${ts}`. This prevents the same trigger from firing multiple times for duplicate Slack events.
178
+
179
+ ### Hot Reload
180
+
181
+ Message triggers are rebuilt when configuration is hot-reloaded via `updateConfig()`. Adding, removing, or modifying triggers in `.visor.yaml` takes effect on the next config reload without restarting the bot.
182
+
183
+ ### Example: CI/CD Failure Monitor
184
+
185
+ ```yaml
186
+ scheduler:
187
+ on_message:
188
+ cicd-failures:
189
+ channels: ["C0CICD"]
190
+ from_bots: true
191
+ contains: ["failed", "error", "broken"]
192
+ match: "build.*#\\d+.*(failed|error)"
193
+ threads: root_only
194
+ workflow: analyze-failure
195
+ inputs:
196
+ notify_team: true
197
+
198
+ steps:
199
+ analyze-failure:
200
+ type: ai
201
+ on: [slack_message]
202
+ schema:
203
+ type: object
204
+ properties:
205
+ text:
206
+ type: string
207
+ severity:
208
+ type: string
209
+ enum: [low, medium, high, critical]
210
+ required: [text, severity]
211
+ prompt: |
212
+ A CI/CD failure was detected. Analyze the failure message and provide:
213
+ 1. Root cause analysis
214
+ 2. Suggested fix
215
+ 3. Severity assessment
216
+
217
+ Failure message: {{ event.text }}
218
+ ```
219
+
66
220
  ## Static Cron Jobs
67
221
 
68
222
  Static cron jobs are defined in your configuration file and always run regardless of permission settings. They're ideal for recurring organizational tasks:
@@ -398,6 +552,7 @@ src/
398
552
  │ ├── schedule-parser.ts # Natural language parsing utilities
399
553
  │ ├── scheduler.ts # Generic scheduler daemon
400
554
  │ ├── schedule-tool.ts # AI tool for schedule management
555
+ │ ├── message-trigger.ts # Slack message trigger evaluator
401
556
  │ ├── cli-handler.ts # CLI command handlers
402
557
  │ └── store/ # Storage backends
403
558
  │ ├── index.ts # Backend factory
@@ -418,6 +573,7 @@ src/
418
573
  |-----------|---------|
419
574
  | `Scheduler` | Main daemon that checks for due schedules and executes them |
420
575
  | `ScheduleStore` | Singleton for persisting schedules to JSON |
576
+ | `MessageTriggerEvaluator` | Evaluates Slack messages against `on_message` triggers |
421
577
  | `ScheduleOutputAdapter` | Interface for output destinations |
422
578
  | `SlackOutputAdapter` | Implements output posting for Slack |
423
579
  | `schedule-tool` | AI tool definition and handler |
@@ -9,6 +9,7 @@ Visor provides bidirectional Slack integration through Socket Mode, enabling int
9
9
  - [Configuration](#configuration)
10
10
  - [Features](#features)
11
11
  - [Example Workflows](#example-workflows)
12
+ - [Message Triggers](#message-triggers)
12
13
  - [Troubleshooting](#troubleshooting)
13
14
  - [Related Documentation](#related-documentation)
14
15
 
@@ -474,6 +475,53 @@ Log messages include:
474
475
  - `[slack-frontend]` - Message posting and reactions
475
476
  - `[prompt-state]` - Human input state management
476
477
 
478
+ ## Message Triggers
479
+
480
+ Message triggers allow Visor to react to Slack messages in specific channels without requiring an @mention. This is configured via `scheduler.on_message` and is ideal for monitoring bot notifications (e.g., CI/CD failures, deployment alerts).
481
+
482
+ ### Quick Example
483
+
484
+ ```yaml
485
+ scheduler:
486
+ on_message:
487
+ cicd-watcher:
488
+ channels: ["C0CICD"]
489
+ from_bots: true
490
+ contains: ["failed", "error"]
491
+ workflow: handle-cicd-failure
492
+
493
+ steps:
494
+ handle-cicd-failure:
495
+ type: ai
496
+ on: [slack_message]
497
+ prompt: "Analyze this CI/CD failure and suggest a fix."
498
+ ```
499
+
500
+ When a message matching the filters appears in the specified channel, Visor dispatches the configured workflow asynchronously. The workflow receives the full Slack event context including message text, sender, channel, and thread conversation history (for thread replies).
501
+
502
+ ### Key Features
503
+
504
+ - **No @mention required**: Triggers fire based on message content, channel, user, and thread scope
505
+ - **Bot message support**: Set `from_bots: true` to react to messages from other bots (CI systems, monitoring tools)
506
+ - **Coexists with @mention path**: A message can trigger both a message trigger workflow and the normal @mention-based dispatch
507
+ - **Hot reload**: Trigger configuration is rebuilt on config hot-reload without restarting the bot
508
+ - **Deduplication**: Built-in dedup prevents duplicate workflow dispatches for the same Slack event
509
+
510
+ ### Filter Options
511
+
512
+ | Filter | Description |
513
+ |--------|-------------|
514
+ | `channels` | Channel IDs (wildcard suffix supported, e.g., `CENG*`) |
515
+ | `from` | Specific user IDs |
516
+ | `from_bots` | Allow bot messages (default: false) |
517
+ | `contains` | Keyword match (case-insensitive, any = match) |
518
+ | `match` | Regex pattern |
519
+ | `threads` | `root_only`, `thread_only`, or `any` (default) |
520
+
521
+ All specified filters must pass (AND). Within `contains`, any keyword suffices (OR). Omitted filters match everything.
522
+
523
+ See [Scheduler - Message Triggers](./scheduler.md#message-triggers-on_message) for complete configuration reference.
524
+
477
525
  ## Scheduled Reminders
478
526
 
479
527
  The scheduler integrates with Slack to deliver scheduled reminders and workflow results. See [Scheduler](./scheduler.md) for full documentation.
@@ -4,7 +4,7 @@
4
4
  * in compliance with the Elastic License 2.0.
5
5
  */
6
6
  import type { Schedule, ScheduleLimits } from '../../scheduler/schedule-store';
7
- import type { ScheduleStoreBackend, ScheduleStoreStats, StorageConfig, HAConfig } from '../../scheduler/store/types';
7
+ import type { ScheduleStoreBackend, ScheduleStoreStats, StorageConfig, HAConfig, MessageTrigger } from '../../scheduler/store/types';
8
8
  /**
9
9
  * Enterprise Knex-backed store for PostgreSQL, MySQL, and MSSQL
10
10
  */
@@ -37,5 +37,11 @@ export declare class KnexStoreBackend implements ScheduleStoreBackend {
37
37
  releaseLock(lockId: string, lockToken: string): Promise<void>;
38
38
  renewLock(lockId: string, lockToken: string, ttlSeconds: number): Promise<boolean>;
39
39
  flush(): Promise<void>;
40
+ createTrigger(trigger: Omit<MessageTrigger, 'id' | 'createdAt'>): Promise<MessageTrigger>;
41
+ getTrigger(id: string): Promise<MessageTrigger | undefined>;
42
+ updateTrigger(id: string, patch: Partial<MessageTrigger>): Promise<MessageTrigger | undefined>;
43
+ deleteTrigger(id: string): Promise<boolean>;
44
+ getTriggersByCreator(creatorId: string): Promise<MessageTrigger[]>;
45
+ getActiveTriggers(): Promise<MessageTrigger[]>;
40
46
  }
41
47
  //# sourceMappingURL=knex-store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"knex-store.d.ts","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/enterprise/scheduler/knex-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,KAAK,EACV,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EACb,QAAQ,EAET,MAAM,6BAA6B,CAAC;AA+FrC;;GAEG;AACH,qBAAa,gBAAiB,YAAW,oBAAoB;IAC3D,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,UAAU,CAAyB;gBAGzC,MAAM,EAAE,YAAY,GAAG,OAAO,GAAG,OAAO,EACxC,aAAa,EAAE,aAAa,EAC5B,SAAS,CAAC,EAAE,QAAQ;IAMhB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAkDjC,OAAO,CAAC,uBAAuB;IAW/B,OAAO,CAAC,oBAAoB;IAkB5B,OAAO,CAAC,gBAAgB;IA4BxB,OAAO,CAAC,eAAe;IAWjB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YAOjB,aAAa;IA4C3B,OAAO,CAAC,OAAO;IAST,MAAM,CACV,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,GAAG,QAAQ,CAAC,GACpF,OAAO,CAAC,QAAQ,CAAC;IAkBd,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAM9C,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAgB3E,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYpC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAMpD,kBAAkB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAMzC,eAAe,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAsBlD,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAW5E,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAM7B,QAAQ,IAAI,OAAO,CAAC,kBAAkB,CAAC;IA4BvC,cAAc,CAClB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,OAAO,EACpB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC;IAqCV,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAmC1F,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7D,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAalF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
1
+ {"version":3,"file":"knex-store.d.ts","sourceRoot":"","sources":["file:///home/runner/work/visor/visor/src/enterprise/scheduler/knex-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ # =============================================================================
2
+ # Example: Using code-talk as an AI Custom Tool
3
+ # =============================================================================
4
+ #
5
+ # This example shows how to use the code-talk workflow as an AI tool,
6
+ # allowing an AI assistant to explore your codebase on demand.
7
+ #
8
+ # Usage:
9
+ # visor --config examples/code-talk-as-tool.yaml --message "Help me understand the codebase"
10
+ #
11
+ # =============================================================================
12
+
13
+ version: "1.0"
14
+
15
+ imports:
16
+ - visor://code-talk.yaml
17
+
18
+ # Define a project-specific wrapper that can be used as a tool
19
+ checks:
20
+ # Get user request
21
+ get-request:
22
+ type: human-input
23
+ prompt: "What would you like help with?"
24
+ placeholder: "e.g., Help me understand how the API endpoints work"
25
+
26
+ # AI assistant with code exploration tool
27
+ assistant:
28
+ type: ai
29
+ depends_on: [get-request]
30
+ ai:
31
+ skip_code_context: true
32
+ prompt_type: general
33
+ prompt: |
34
+ You are a helpful assistant for this project.
35
+
36
+ The user asked: {{ outputs['get-request'].text }}
37
+
38
+ You have access to the code-talk tool which can explore the codebase
39
+ and answer technical questions with code references.
40
+
41
+ Use the code-talk tool when you need to:
42
+ - Find specific implementations
43
+ - Understand how components work
44
+ - Locate relevant code files
45
+ - Answer technical questions about the codebase
46
+
47
+ After getting information from the tool, provide a clear and helpful response.
48
+
49
+ ai_custom_tools:
50
+ # Use code-talk directly as a tool
51
+ - workflow: code-talk
52
+ args:
53
+ # Pre-configure with your project settings
54
+ architecture: |
55
+ # Project Architecture
56
+ Describe your project here.
57
+
58
+ projects:
59
+ - id: my-project
60
+ repo: your-org/your-repo
61
+ description: Main project codebase
62
+
63
+ max_projects: 1
64
+
65
+ # Show the result
66
+ show-result:
67
+ type: log
68
+ depends_on: [assistant]
69
+ message: |
70
+ ===============================================================
71
+ Assistant Response
72
+ ===============================================================
73
+
74
+ {{ outputs['assistant'].content }}
75
+
76
+ ===============================================================
@@ -0,0 +1,68 @@
1
+ # =============================================================================
2
+ # Example: Using code-talk as a Standard Workflow
3
+ # =============================================================================
4
+ #
5
+ # This example shows how to use the code-talk workflow for interactive
6
+ # code exploration in your project.
7
+ #
8
+ # Usage:
9
+ # visor --config examples/code-talk-workflow.yaml --message "How does auth work?"
10
+ #
11
+ # =============================================================================
12
+
13
+ version: "1.0"
14
+
15
+ imports:
16
+ - visor://code-talk.yaml
17
+
18
+ checks:
19
+ # Get the user's question
20
+ get-question:
21
+ type: human-input
22
+ prompt: "What would you like to know about the codebase?"
23
+ placeholder: "e.g., How does the authentication system work?"
24
+
25
+ # Call code-talk with your project configuration
26
+ explore:
27
+ type: workflow
28
+ workflow: code-talk
29
+ criticality: internal
30
+ depends_on: [get-question]
31
+ args:
32
+ question: "{{ outputs['get-question'].text }}"
33
+
34
+ # Customize this for your project
35
+ architecture: |
36
+ # Project Architecture
37
+
38
+ ## Overview
39
+ Describe your project architecture here.
40
+
41
+ ## Key Components
42
+ - Component A: Description
43
+ - Component B: Description
44
+
45
+ ## Project IDs
46
+ | ID | Description |
47
+ |----|-------------|
48
+ | `my-project` | Main project codebase |
49
+
50
+ ## Key Directories
51
+ - `src/` - Source code
52
+ - `tests/` - Test files
53
+
54
+ # GitHub repository for docs (optional)
55
+ docs_repo: your-org/your-repo
56
+ docs_ref: main
57
+
58
+ # Define your projects
59
+ projects:
60
+ - id: my-project
61
+ repo: your-org/your-repo
62
+ description: |
63
+ Main project codebase:
64
+ - src/ - Source code
65
+ - tests/ - Test files
66
+
67
+ # Limit to single project for focused analysis
68
+ max_projects: 1
@@ -0,0 +1,66 @@
1
+ # =============================================================================
2
+ # Example: Using intent-router for Assistant Routing
3
+ # =============================================================================
4
+ #
5
+ # Usage:
6
+ # visor --config examples/intent-router-workflow.yaml --message "Summarize this thread"
7
+ #
8
+ # =============================================================================
9
+
10
+ version: "1.0"
11
+
12
+ imports:
13
+ - visor://intent-router.yaml
14
+
15
+ checks:
16
+ ask:
17
+ type: human-input
18
+ prompt: "What should I do with this message?"
19
+ placeholder: "e.g., Summarize the thread and list action items"
20
+
21
+ route-intent:
22
+ type: workflow
23
+ workflow: intent-router
24
+ criticality: internal
25
+ depends_on: [ask]
26
+ args:
27
+ question: "{{ outputs['ask'].text }}"
28
+ intents:
29
+ - id: chat
30
+ description: general Q&A or small talk
31
+ - id: thread_summary
32
+ description: user explicitly asks for a summary of the thread
33
+ - id: code_help
34
+ description: questions about code, debugging, or implementation details
35
+ tags:
36
+ - id: jira
37
+ description: request references Jira tickets or needs Jira data
38
+ - id: confluence
39
+ description: request references Confluence pages or needs Confluence data
40
+ - id: codebase
41
+ description: request needs codebase or implementation details
42
+ routing_instructions: |
43
+ Prefer thread_summary when the user asks to summarize or extract action items.
44
+
45
+ chat-answer:
46
+ type: ai
47
+ depends_on: [route-intent]
48
+ if: "outputs['route-intent']?.intent === 'chat'"
49
+ prompt: |
50
+ Answer the user's question:
51
+ {{ outputs['route-intent'].topic }}
52
+
53
+ summarize-thread:
54
+ type: ai
55
+ depends_on: [route-intent]
56
+ if: "outputs['route-intent']?.intent === 'thread_summary'"
57
+ prompt: |
58
+ Summarize the thread and list action items.
59
+
60
+ code-help:
61
+ type: ai
62
+ depends_on: [route-intent]
63
+ if: "outputs['route-intent']?.intent === 'code_help'"
64
+ prompt: |
65
+ Provide a short technical explanation for:
66
+ {{ outputs['route-intent'].topic }}