@probelabs/visor 0.1.127 → 0.1.129
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 +31 -1
- package/defaults/.visor.yaml +420 -0
- package/dist/ai-review-service.d.ts +1 -0
- package/dist/ai-review-service.d.ts.map +1 -1
- package/dist/cli-main.d.ts.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/daemon.js +19 -0
- package/dist/defaults/.visor.yaml +420 -0
- package/dist/docs/commands.md +1 -1
- package/dist/docs/debugging.md +133 -0
- package/dist/docs/dev-playbook.md +10 -0
- package/dist/docs/index.md +1 -0
- package/dist/docs/scheduler.md +503 -0
- package/dist/docs/slack-integration.md +21 -0
- package/dist/docs/timeouts.md +1 -1
- package/dist/docs/workflow-creation-guide.md +39 -0
- package/dist/examples/README.md +30 -0
- package/dist/examples/calculator-config.yaml +4 -4
- package/dist/examples/sandbox-basic.yaml +18 -0
- package/dist/examples/sandbox-cache.yaml +32 -0
- package/dist/examples/sandbox-dockerfile-inline.yaml +22 -0
- package/dist/examples/sandbox-env-passthrough.yaml +26 -0
- package/dist/examples/sandbox-multi-env.yaml +27 -0
- package/dist/examples/sandbox-read-only.yaml +33 -0
- package/dist/examples/scheduler-example.yaml +118 -0
- package/dist/frontends/host.d.ts.map +1 -1
- package/dist/frontends/slack-frontend.d.ts.map +1 -1
- package/dist/generated/config-schema.d.ts +230 -9
- package/dist/generated/config-schema.d.ts.map +1 -1
- package/dist/index.js +13676 -1604
- package/dist/mcp-server.d.ts +8 -8
- package/dist/{traces/run-2026-02-01T09-59-08-165Z.ndjson → output/traces/run-2026-02-08T18-16-04-160Z.ndjson} +84 -84
- package/dist/{traces/run-2026-02-01T09-59-52-595Z.ndjson → output/traces/run-2026-02-08T18-16-51-253Z.ndjson} +1029 -1029
- package/dist/providers/ai-check-provider.d.ts +16 -0
- package/dist/providers/ai-check-provider.d.ts.map +1 -1
- package/dist/providers/check-provider.interface.d.ts +5 -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/log-check-provider.d.ts.map +1 -1
- package/dist/providers/mcp-check-provider.d.ts +3 -0
- package/dist/providers/mcp-check-provider.d.ts.map +1 -1
- package/dist/providers/mcp-custom-sse-server.d.ts +22 -2
- package/dist/providers/mcp-custom-sse-server.d.ts.map +1 -1
- package/dist/providers/workflow-check-provider.d.ts.map +1 -1
- package/dist/providers/workflow-tool-executor.d.ts +2 -0
- package/dist/providers/workflow-tool-executor.d.ts.map +1 -1
- package/dist/sandbox/cache-volume-manager.d.ts +48 -0
- package/dist/sandbox/cache-volume-manager.d.ts.map +1 -0
- package/dist/sandbox/check-runner.d.ts +25 -0
- package/dist/sandbox/check-runner.d.ts.map +1 -0
- package/dist/sandbox/docker-compose-sandbox.d.ts +25 -0
- package/dist/sandbox/docker-compose-sandbox.d.ts.map +1 -0
- package/dist/sandbox/docker-image-sandbox.d.ts +32 -0
- package/dist/sandbox/docker-image-sandbox.d.ts.map +1 -0
- package/dist/sandbox/env-filter.d.ts +19 -0
- package/dist/sandbox/env-filter.d.ts.map +1 -0
- package/dist/sandbox/index.d.ts +9 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/sandbox/sandbox-manager.d.ts +39 -0
- package/dist/sandbox/sandbox-manager.d.ts.map +1 -0
- package/dist/sandbox/sandbox-telemetry.d.ts +9 -0
- package/dist/sandbox/sandbox-telemetry.d.ts.map +1 -0
- package/dist/sandbox/trace-ingester.d.ts +19 -0
- package/dist/sandbox/trace-ingester.d.ts.map +1 -0
- package/dist/sandbox/types.d.ts +149 -0
- package/dist/sandbox/types.d.ts.map +1 -0
- package/dist/scheduler/cli-handler.d.ts +6 -0
- package/dist/scheduler/cli-handler.d.ts.map +1 -0
- package/dist/scheduler/index.d.ts +14 -0
- package/dist/scheduler/index.d.ts.map +1 -0
- package/dist/scheduler/schedule-parser.d.ts +34 -0
- package/dist/scheduler/schedule-parser.d.ts.map +1 -0
- package/dist/scheduler/schedule-store.d.ts +182 -0
- package/dist/scheduler/schedule-store.d.ts.map +1 -0
- package/dist/scheduler/schedule-tool.d.ts +137 -0
- package/dist/scheduler/schedule-tool.d.ts.map +1 -0
- package/dist/scheduler/scheduler.d.ts +195 -0
- package/dist/scheduler/scheduler.d.ts.map +1 -0
- package/dist/sdk/check-provider-registry-ACRGIYOB.mjs +28 -0
- package/dist/sdk/check-provider-registry-VYHKFHK2.mjs +28 -0
- package/dist/sdk/{chunk-CNX7V5JK.mjs → chunk-25IC7KXZ.mjs} +2 -2
- package/dist/sdk/{chunk-IHZOSIF4.mjs → chunk-2KB35MB7.mjs} +3 -3
- package/dist/sdk/{chunk-HQL734ZI.mjs → chunk-6W75IMDC.mjs} +3 -3
- package/dist/sdk/{chunk-XWJPT5KQ.mjs → chunk-7YSOINAQ.mjs} +392 -18
- package/dist/sdk/chunk-7YSOINAQ.mjs.map +1 -0
- package/dist/sdk/{chunk-3OMWVM6J.mjs → chunk-B7BVQM5K.mjs} +2 -2
- package/dist/sdk/chunk-BDGUM6BA.mjs +38825 -0
- package/dist/sdk/chunk-BDGUM6BA.mjs.map +1 -0
- package/dist/sdk/{chunk-VW2GBXQT.mjs → chunk-D5KI4YQ4.mjs} +3 -3
- package/dist/sdk/chunk-DGZPPGJJ.mjs +38825 -0
- package/dist/sdk/chunk-DGZPPGJJ.mjs.map +1 -0
- package/dist/sdk/chunk-H5BOW5CR.mjs +91 -0
- package/dist/sdk/chunk-H5BOW5CR.mjs.map +1 -0
- package/dist/sdk/{chunk-YSN4G6CI.mjs → chunk-HEX3RL32.mjs} +81 -3
- package/dist/sdk/{chunk-YSN4G6CI.mjs.map → chunk-HEX3RL32.mjs.map} +1 -1
- package/dist/sdk/{chunk-ZYAUYXSW.mjs → chunk-J5RGJQ53.mjs} +14 -3
- package/dist/sdk/{chunk-ZYAUYXSW.mjs.map → chunk-J5RGJQ53.mjs.map} +1 -1
- package/dist/sdk/{chunk-WMJKH4XE.mjs → chunk-J7LXIPZS.mjs} +16 -1
- package/dist/sdk/{chunk-EXFGO4FX.mjs → chunk-KFKHU6CM.mjs} +2 -2
- package/dist/sdk/{chunk-MPS4HVQI.mjs → chunk-N7HO6KKC.mjs} +8 -8
- package/dist/sdk/{chunk-O5EZDNYL.mjs → chunk-NCWIZVOT.mjs} +2 -2
- package/dist/sdk/{chunk-3NMLT3YS.mjs → chunk-PO7X5XI7.mjs} +3 -3
- package/dist/sdk/{chunk-BHOKBQPB.mjs → chunk-R5Z7YWPB.mjs} +5 -5
- package/dist/sdk/{chunk-EORMDOZU.mjs → chunk-SGS2VMEL.mjs} +7 -7
- package/dist/sdk/{chunk-BOVFH3LI.mjs → chunk-VF6XIUE4.mjs} +21 -10
- package/dist/sdk/chunk-VF6XIUE4.mjs.map +1 -0
- package/dist/sdk/{chunk-J2QWVDXK.mjs → chunk-XDLQ3UNF.mjs} +3 -3
- package/dist/sdk/{chunk-S2RUE2RG.mjs → chunk-XR7XXGL7.mjs} +3 -3
- package/dist/sdk/{chunk-NAW3DB3I.mjs → chunk-XXAEN5KU.mjs} +3 -3
- package/dist/sdk/command-executor-DVVXERLR.mjs +14 -0
- package/dist/sdk/config-7VTT64SQ.mjs +16 -0
- package/dist/sdk/config-merger-RKCZJQ44.mjs +10 -0
- package/dist/sdk/event-bus-5K3Y2FCS.mjs +43 -0
- package/dist/sdk/{event-bus-5BEVPQ6T.mjs.map → event-bus-5K3Y2FCS.mjs.map} +1 -1
- package/dist/sdk/failure-condition-evaluator-4WMDF4Q3.mjs +17 -0
- package/dist/sdk/git-repository-analyzer-QFMW6WIS.mjs +471 -0
- package/dist/sdk/git-repository-analyzer-QFMW6WIS.mjs.map +1 -0
- package/dist/sdk/{github-frontend-5PCKKHVC.mjs → github-frontend-3N2NLO66.mjs} +520 -588
- package/dist/sdk/github-frontend-3N2NLO66.mjs.map +1 -0
- package/dist/sdk/host-ONVMEHAA.mjs +63 -0
- package/dist/sdk/host-ONVMEHAA.mjs.map +1 -0
- package/dist/sdk/{liquid-extensions-I7O7KMHF.mjs → liquid-extensions-5IZLTFSZ.mjs} +8 -8
- package/dist/sdk/memory-store-3N4AZCYB.mjs +12 -0
- package/dist/sdk/{metrics-7PP3EJUH.mjs → metrics-GXQ2EDXA.mjs} +4 -4
- package/dist/sdk/ndjson-sink-FD2PSXGD.mjs +52 -0
- package/dist/sdk/{ndjson-sink-B4V4NTAQ.mjs.map → ndjson-sink-FD2PSXGD.mjs.map} +1 -1
- package/dist/sdk/{prompt-state-EZYOUG75.mjs → prompt-state-YHGXB2OA.mjs} +5 -5
- package/dist/sdk/{renderer-schema-CKFB5NDB.mjs → renderer-schema-CMXOLNIG.mjs} +4 -4
- package/dist/sdk/routing-S3Y7T2X3.mjs +24 -0
- package/dist/sdk/sdk.d.mts +212 -4
- package/dist/sdk/sdk.d.ts +212 -4
- package/dist/sdk/sdk.js +26927 -6264
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +23 -1278
- package/dist/sdk/sdk.mjs.map +1 -1
- package/dist/sdk/session-registry-6PV6SGEJ.mjs +10 -0
- package/dist/sdk/slack-frontend-R3M2CACB.mjs +899 -0
- package/dist/sdk/slack-frontend-R3M2CACB.mjs.map +1 -0
- package/dist/sdk/{trace-helpers-VP6QYVBX.mjs → trace-helpers-YHNPC7MR.mjs} +4 -4
- package/dist/sdk/tracer-init-XPRWKMZT.mjs +10 -0
- package/dist/sdk/tui-frontend-S546M7A7.mjs +281 -0
- package/dist/sdk/tui-frontend-S546M7A7.mjs.map +1 -0
- package/dist/sdk/workflow-check-provider-4F3432ZP.mjs +28 -0
- package/dist/sdk/workflow-check-provider-A44PBPG2.mjs +28 -0
- package/dist/sdk/workflow-check-provider-A44PBPG2.mjs.map +1 -0
- package/dist/sdk/workflow-registry-ZAYYXLEP.mjs +12 -0
- package/dist/sdk/workflow-registry-ZAYYXLEP.mjs.map +1 -0
- package/dist/slack/client.d.ts +28 -0
- package/dist/slack/client.d.ts.map +1 -1
- package/dist/slack/schedule-tool-handler.d.ts +46 -0
- package/dist/slack/schedule-tool-handler.d.ts.map +1 -0
- package/dist/slack/slack-output-adapter.d.ts +44 -0
- package/dist/slack/slack-output-adapter.d.ts.map +1 -0
- package/dist/slack/socket-runner.d.ts +22 -0
- package/dist/slack/socket-runner.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/sandbox-routing.d.ts +21 -0
- package/dist/state-machine/dispatch/sandbox-routing.d.ts.map +1 -0
- package/dist/state-machine/states/level-dispatch.d.ts.map +1 -1
- package/dist/state-machine-execution-engine.d.ts.map +1 -1
- package/dist/test-runner/index.d.ts +5 -0
- package/dist/test-runner/index.d.ts.map +1 -1
- package/dist/{output/traces/run-2026-02-01T09-59-08-165Z.ndjson → traces/run-2026-02-08T18-16-04-160Z.ndjson} +84 -84
- package/dist/{output/traces/run-2026-02-01T09-59-52-595Z.ndjson → traces/run-2026-02-08T18-16-51-253Z.ndjson} +1029 -1029
- package/dist/tui/chat-runner.d.ts +39 -0
- package/dist/tui/chat-runner.d.ts.map +1 -0
- package/dist/tui/chat-state.d.ts +56 -0
- package/dist/tui/chat-state.d.ts.map +1 -0
- package/dist/tui/chat-tui.d.ts +69 -0
- package/dist/tui/chat-tui.d.ts.map +1 -0
- package/dist/tui/components/chat-box.d.ts +33 -0
- package/dist/tui/components/chat-box.d.ts.map +1 -0
- package/dist/tui/components/input-bar.d.ts +50 -0
- package/dist/tui/components/input-bar.d.ts.map +1 -0
- package/dist/tui/components/status-bar.d.ts +31 -0
- package/dist/tui/components/status-bar.d.ts.map +1 -0
- package/dist/tui/components/trace-viewer.d.ts +73 -0
- package/dist/tui/components/trace-viewer.d.ts.map +1 -0
- package/dist/tui/index.d.ts +14 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/tui-frontend.d.ts +29 -0
- package/dist/tui/tui-frontend.d.ts.map +1 -0
- package/dist/types/bot.d.ts +35 -0
- package/dist/types/bot.d.ts.map +1 -1
- package/dist/types/config.d.ts +152 -3
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/engine.d.ts +3 -0
- package/dist/types/engine.d.ts.map +1 -1
- package/dist/utils/sandbox.d.ts.map +1 -1
- package/dist/utils/workspace-manager.d.ts +22 -2
- package/dist/utils/workspace-manager.d.ts.map +1 -1
- package/dist/utils/worktree-manager.d.ts +2 -1
- package/dist/utils/worktree-manager.d.ts.map +1 -1
- package/package.json +4 -2
- package/dist/docs/NPM_USAGE.md +0 -281
- package/dist/generated/config-schema.json +0 -2161
- package/dist/sdk/check-provider-registry-CVUONJ5A.mjs +0 -28
- package/dist/sdk/chunk-BOVFH3LI.mjs.map +0 -1
- package/dist/sdk/chunk-TS6BUNAI.mjs +0 -17722
- package/dist/sdk/chunk-TS6BUNAI.mjs.map +0 -1
- package/dist/sdk/chunk-XWJPT5KQ.mjs.map +0 -1
- package/dist/sdk/command-executor-Q7MHJKZJ.mjs +0 -14
- package/dist/sdk/config-DXX64GD3.mjs +0 -16
- package/dist/sdk/config-merger-PX3WIT57.mjs +0 -10
- package/dist/sdk/event-bus-5BEVPQ6T.mjs +0 -35
- package/dist/sdk/failure-condition-evaluator-G4HMJPXF.mjs +0 -17
- package/dist/sdk/git-repository-analyzer-HJC4MYW4.mjs +0 -458
- package/dist/sdk/git-repository-analyzer-HJC4MYW4.mjs.map +0 -1
- package/dist/sdk/github-frontend-5PCKKHVC.mjs.map +0 -1
- package/dist/sdk/host-H3AWNZ2F.mjs +0 -52
- package/dist/sdk/host-H3AWNZ2F.mjs.map +0 -1
- package/dist/sdk/memory-store-RW5N2NGJ.mjs +0 -12
- package/dist/sdk/ndjson-sink-B4V4NTAQ.mjs +0 -44
- package/dist/sdk/routing-QHTGDIXF.mjs +0 -24
- package/dist/sdk/session-registry-4E6YRQ77.mjs +0 -10
- package/dist/sdk/slack-frontend-JUT3TYVC.mjs +0 -821
- package/dist/sdk/slack-frontend-JUT3TYVC.mjs.map +0 -1
- package/dist/sdk/tracer-init-GSLPPLCD.mjs +0 -10
- package/dist/sdk/workflow-check-provider-3IWBAZP7.mjs +0 -28
- package/dist/sdk/workflow-registry-KFWSDSLM.mjs +0 -12
- package/dist/tui.d.ts +0 -51
- package/dist/tui.d.ts.map +0 -1
- /package/dist/sdk/{check-provider-registry-CVUONJ5A.mjs.map → check-provider-registry-ACRGIYOB.mjs.map} +0 -0
- /package/dist/sdk/{chunk-WMJKH4XE.mjs.map → check-provider-registry-VYHKFHK2.mjs.map} +0 -0
- /package/dist/sdk/{chunk-CNX7V5JK.mjs.map → chunk-25IC7KXZ.mjs.map} +0 -0
- /package/dist/sdk/{chunk-IHZOSIF4.mjs.map → chunk-2KB35MB7.mjs.map} +0 -0
- /package/dist/sdk/{chunk-HQL734ZI.mjs.map → chunk-6W75IMDC.mjs.map} +0 -0
- /package/dist/sdk/{chunk-3OMWVM6J.mjs.map → chunk-B7BVQM5K.mjs.map} +0 -0
- /package/dist/sdk/{chunk-VW2GBXQT.mjs.map → chunk-D5KI4YQ4.mjs.map} +0 -0
- /package/dist/sdk/{command-executor-Q7MHJKZJ.mjs.map → chunk-J7LXIPZS.mjs.map} +0 -0
- /package/dist/sdk/{chunk-EXFGO4FX.mjs.map → chunk-KFKHU6CM.mjs.map} +0 -0
- /package/dist/sdk/{chunk-MPS4HVQI.mjs.map → chunk-N7HO6KKC.mjs.map} +0 -0
- /package/dist/sdk/{chunk-O5EZDNYL.mjs.map → chunk-NCWIZVOT.mjs.map} +0 -0
- /package/dist/sdk/{chunk-3NMLT3YS.mjs.map → chunk-PO7X5XI7.mjs.map} +0 -0
- /package/dist/sdk/{chunk-BHOKBQPB.mjs.map → chunk-R5Z7YWPB.mjs.map} +0 -0
- /package/dist/sdk/{chunk-EORMDOZU.mjs.map → chunk-SGS2VMEL.mjs.map} +0 -0
- /package/dist/sdk/{chunk-J2QWVDXK.mjs.map → chunk-XDLQ3UNF.mjs.map} +0 -0
- /package/dist/sdk/{chunk-S2RUE2RG.mjs.map → chunk-XR7XXGL7.mjs.map} +0 -0
- /package/dist/sdk/{chunk-NAW3DB3I.mjs.map → chunk-XXAEN5KU.mjs.map} +0 -0
- /package/dist/sdk/{config-DXX64GD3.mjs.map → command-executor-DVVXERLR.mjs.map} +0 -0
- /package/dist/sdk/{config-merger-PX3WIT57.mjs.map → config-7VTT64SQ.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-G4HMJPXF.mjs.map → config-merger-RKCZJQ44.mjs.map} +0 -0
- /package/dist/sdk/{liquid-extensions-I7O7KMHF.mjs.map → failure-condition-evaluator-4WMDF4Q3.mjs.map} +0 -0
- /package/dist/sdk/{memory-store-RW5N2NGJ.mjs.map → liquid-extensions-5IZLTFSZ.mjs.map} +0 -0
- /package/dist/sdk/{metrics-7PP3EJUH.mjs.map → memory-store-3N4AZCYB.mjs.map} +0 -0
- /package/dist/sdk/{prompt-state-EZYOUG75.mjs.map → metrics-GXQ2EDXA.mjs.map} +0 -0
- /package/dist/sdk/{routing-QHTGDIXF.mjs.map → prompt-state-YHGXB2OA.mjs.map} +0 -0
- /package/dist/sdk/{renderer-schema-CKFB5NDB.mjs.map → renderer-schema-CMXOLNIG.mjs.map} +0 -0
- /package/dist/sdk/{session-registry-4E6YRQ77.mjs.map → routing-S3Y7T2X3.mjs.map} +0 -0
- /package/dist/sdk/{trace-helpers-VP6QYVBX.mjs.map → session-registry-6PV6SGEJ.mjs.map} +0 -0
- /package/dist/sdk/{tracer-init-GSLPPLCD.mjs.map → trace-helpers-YHNPC7MR.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-3IWBAZP7.mjs.map → tracer-init-XPRWKMZT.mjs.map} +0 -0
- /package/dist/sdk/{workflow-registry-KFWSDSLM.mjs.map → workflow-check-provider-4F3432ZP.mjs.map} +0 -0
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
# Scheduler
|
|
2
|
+
|
|
3
|
+
The Visor scheduler provides a generic, frontend-agnostic system for executing workflows and reminders at specified times. It supports both static schedules defined in YAML configuration and dynamic schedules created via AI tool at runtime.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The scheduler operates in two modes:
|
|
8
|
+
|
|
9
|
+
1. **Workflow Schedules**: Execute a named workflow/check from your configuration
|
|
10
|
+
2. **Simple Reminders**: Post a message or run it through the visor pipeline (e.g., for AI-powered responses)
|
|
11
|
+
|
|
12
|
+
Output destinations (Slack, GitHub, webhooks) are handled by **output adapters**, making the scheduler truly frontend-agnostic. When running with Slack, the `SlackOutputAdapter` automatically posts results back to the appropriate channel or DM.
|
|
13
|
+
|
|
14
|
+
## Configuration
|
|
15
|
+
|
|
16
|
+
Add scheduler settings to your `.visor.yaml`:
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
scheduler:
|
|
20
|
+
enabled: true
|
|
21
|
+
storage:
|
|
22
|
+
path: .visor/schedules.json
|
|
23
|
+
default_timezone: America/New_York
|
|
24
|
+
check_interval_ms: 60000 # How often to check for due schedules
|
|
25
|
+
|
|
26
|
+
# Limits for dynamic schedules (created via AI tool)
|
|
27
|
+
limits:
|
|
28
|
+
max_per_user: 25
|
|
29
|
+
max_recurring_per_user: 10
|
|
30
|
+
max_global: 1000
|
|
31
|
+
|
|
32
|
+
# Permissions for dynamic schedule creation
|
|
33
|
+
permissions:
|
|
34
|
+
allow_personal: true # Allow schedules via DM or CLI
|
|
35
|
+
allow_channel: true # Allow channel schedules (Slack)
|
|
36
|
+
allow_dm: true # Allow DM schedules to other users
|
|
37
|
+
allowed_workflows: # Glob patterns for allowed workflows
|
|
38
|
+
- "report-*"
|
|
39
|
+
- "status-*"
|
|
40
|
+
denied_workflows: # Glob patterns for denied workflows
|
|
41
|
+
- "admin-*"
|
|
42
|
+
- "dangerous-*"
|
|
43
|
+
|
|
44
|
+
# Static cron jobs (always allowed, bypass permissions)
|
|
45
|
+
cron:
|
|
46
|
+
daily-standup:
|
|
47
|
+
schedule: "0 9 * * 1-5" # Weekdays at 9am
|
|
48
|
+
workflow: daily-standup
|
|
49
|
+
timezone: America/New_York
|
|
50
|
+
output:
|
|
51
|
+
type: slack
|
|
52
|
+
target: "#engineering"
|
|
53
|
+
|
|
54
|
+
weekly-report:
|
|
55
|
+
schedule: "0 10 * * 1" # Mondays at 10am
|
|
56
|
+
workflow: weekly-report
|
|
57
|
+
inputs:
|
|
58
|
+
team: platform
|
|
59
|
+
output:
|
|
60
|
+
type: slack
|
|
61
|
+
target: "#platform-team"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Static Cron Jobs
|
|
65
|
+
|
|
66
|
+
Static cron jobs are defined in your configuration file and always run regardless of permission settings. They're ideal for recurring organizational tasks:
|
|
67
|
+
|
|
68
|
+
```yaml
|
|
69
|
+
scheduler:
|
|
70
|
+
cron:
|
|
71
|
+
security-scan:
|
|
72
|
+
schedule: "0 2 * * *" # Daily at 2am
|
|
73
|
+
workflow: security-scan
|
|
74
|
+
output:
|
|
75
|
+
type: slack
|
|
76
|
+
target: "#security-alerts"
|
|
77
|
+
|
|
78
|
+
backup-status:
|
|
79
|
+
schedule: "0 6 * * *" # Daily at 6am
|
|
80
|
+
workflow: backup-check
|
|
81
|
+
inputs:
|
|
82
|
+
notify_on_failure: true
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Cron Expression Format
|
|
86
|
+
|
|
87
|
+
Standard 5-field cron expressions:
|
|
88
|
+
- `* * * * *` - minute, hour, day of month, month, day of week
|
|
89
|
+
- `0 9 * * *` - Every day at 9:00 AM
|
|
90
|
+
- `0 9 * * 1-5` - Weekdays at 9:00 AM
|
|
91
|
+
- `*/15 * * * *` - Every 15 minutes
|
|
92
|
+
- `0 0 1 * *` - First day of every month at midnight
|
|
93
|
+
|
|
94
|
+
## Dynamic Schedules (AI Tool)
|
|
95
|
+
|
|
96
|
+
Users can create schedules dynamically through the AI tool. The AI is responsible for:
|
|
97
|
+
|
|
98
|
+
1. **Extracting timing**: Converting natural language to cron expressions or ISO timestamps
|
|
99
|
+
2. **Determining targets**: Using the current channel context (channel ID from conversation)
|
|
100
|
+
3. **Identifying recurrence**: One-time vs recurring schedules
|
|
101
|
+
|
|
102
|
+
### Example Interactions
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
User in DM: "remind me to check builds every day at 9am"
|
|
106
|
+
AI: [calls schedule tool with action=create, reminder_text="check builds",
|
|
107
|
+
cron="0 9 * * *", target_type="dm", target_id="D09SZABNLG3"]
|
|
108
|
+
|
|
109
|
+
User in #security: "run security-scan every Monday at 10am"
|
|
110
|
+
AI: [calls schedule tool with action=create, workflow="security-scan",
|
|
111
|
+
cron="0 10 * * 1", target_type="channel", target_id="C05ABC123"]
|
|
112
|
+
|
|
113
|
+
User in DM: "remind me in 2 hours to review the PR"
|
|
114
|
+
AI: [calls schedule tool with action=create, reminder_text="review the PR",
|
|
115
|
+
run_at="2026-02-08T18:00:00Z", target_type="dm", target_id="D09SZABNLG3"]
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### AI Tool Parameters
|
|
119
|
+
|
|
120
|
+
The AI generates structured parameters:
|
|
121
|
+
|
|
122
|
+
| Parameter | Description |
|
|
123
|
+
|-----------|-------------|
|
|
124
|
+
| `reminder_text` | What to say when the schedule fires |
|
|
125
|
+
| `workflow` | Alternatively, a workflow to execute |
|
|
126
|
+
| `target_type` | "channel", "dm", "thread", or "user" |
|
|
127
|
+
| `target_id` | Slack channel ID (C... or D...) |
|
|
128
|
+
| `cron` | For recurring: cron expression |
|
|
129
|
+
| `run_at` | For one-time: ISO 8601 timestamp |
|
|
130
|
+
| `is_recurring` | Boolean flag |
|
|
131
|
+
|
|
132
|
+
### Permission Controls
|
|
133
|
+
|
|
134
|
+
Dynamic schedules respect the `permissions` configuration:
|
|
135
|
+
|
|
136
|
+
- **allow_personal**: Controls personal schedules (DM context or CLI)
|
|
137
|
+
- **allow_channel**: Controls channel schedules (Slack channels)
|
|
138
|
+
- **allow_dm**: Controls DM schedules to other users
|
|
139
|
+
- **allowed_workflows**: Glob patterns that workflows must match
|
|
140
|
+
- **denied_workflows**: Glob patterns that block workflows (checked first)
|
|
141
|
+
|
|
142
|
+
```yaml
|
|
143
|
+
permissions:
|
|
144
|
+
allow_personal: true
|
|
145
|
+
allow_channel: false # Disable channel schedules
|
|
146
|
+
allow_dm: false # Disable DM schedules
|
|
147
|
+
allowed_workflows:
|
|
148
|
+
- "report-*" # Only allow report workflows
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Schedule Types and Context Restrictions
|
|
152
|
+
|
|
153
|
+
The scheduler determines schedule type based on context and enforces restrictions:
|
|
154
|
+
|
|
155
|
+
| Context | Allowed Schedule Type |
|
|
156
|
+
|---------|----------------------|
|
|
157
|
+
| CLI | personal only |
|
|
158
|
+
| Slack DM | personal only |
|
|
159
|
+
| Slack channel | channel only |
|
|
160
|
+
| Slack group DM | dm only |
|
|
161
|
+
|
|
162
|
+
**Context-Based Enforcement**: When creating a schedule from a DM, you can only create personal schedules. When in a channel, you can only create channel schedules. This prevents cross-context leakage (e.g., personal reminders shouldn't appear when listing schedules in a public channel).
|
|
163
|
+
|
|
164
|
+
### List Filtering
|
|
165
|
+
|
|
166
|
+
When listing schedules, only schedules matching the current context type are shown:
|
|
167
|
+
- In a DM: Only personal schedules
|
|
168
|
+
- In a channel: Only channel schedules
|
|
169
|
+
- In a group DM: Only dm/group schedules
|
|
170
|
+
|
|
171
|
+
This protects privacy - personal reminders created in a DM won't be visible when someone lists schedules in a public channel.
|
|
172
|
+
|
|
173
|
+
## CLI Commands
|
|
174
|
+
|
|
175
|
+
### Start the Scheduler Daemon
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
visor schedule start [--config .visor.yaml]
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Runs the scheduler daemon that checks for and executes due schedules.
|
|
182
|
+
|
|
183
|
+
### List Schedules
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
visor schedule list [--user <userId>] [--status <status>] [--json]
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Shows schedules. Use `--json` for machine-readable output.
|
|
190
|
+
|
|
191
|
+
### Create a Schedule
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
visor schedule create <workflow> --at "<expression>" [--inputs key=value] [--output-type slack] [--output-target #channel]
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Examples:
|
|
198
|
+
```bash
|
|
199
|
+
# One-time schedule
|
|
200
|
+
visor schedule create daily-report --at "tomorrow at 9am"
|
|
201
|
+
|
|
202
|
+
# Recurring schedule
|
|
203
|
+
visor schedule create standup --at "every weekday at 9am" --output-type slack --output-target "#team"
|
|
204
|
+
|
|
205
|
+
# With inputs
|
|
206
|
+
visor schedule create backup-check --at "every day at 2am" --inputs environment=production
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Cancel a Schedule
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
visor schedule cancel <id>
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Pause/Resume
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
visor schedule pause <id>
|
|
219
|
+
visor schedule resume <id>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Output Adapters
|
|
223
|
+
|
|
224
|
+
When a schedule executes, results can be routed to different destinations:
|
|
225
|
+
|
|
226
|
+
### Slack Output
|
|
227
|
+
|
|
228
|
+
```yaml
|
|
229
|
+
output:
|
|
230
|
+
type: slack
|
|
231
|
+
target: "#channel-name" # or @username for DM
|
|
232
|
+
thread_id: "1234567890.123456" # Optional thread
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### GitHub Output
|
|
236
|
+
|
|
237
|
+
```yaml
|
|
238
|
+
output:
|
|
239
|
+
type: github
|
|
240
|
+
target: "owner/repo"
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Webhook Output
|
|
244
|
+
|
|
245
|
+
```yaml
|
|
246
|
+
output:
|
|
247
|
+
type: webhook
|
|
248
|
+
target: "https://example.com/webhook"
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### No Output
|
|
252
|
+
|
|
253
|
+
```yaml
|
|
254
|
+
output:
|
|
255
|
+
type: none
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Integration with Slack
|
|
259
|
+
|
|
260
|
+
When running the Slack bot, the scheduler automatically starts and integrates with the Slack frontend:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
// In socket-runner.ts
|
|
264
|
+
import { Scheduler, createSlackOutputAdapter } from '../scheduler';
|
|
265
|
+
|
|
266
|
+
// Create scheduler
|
|
267
|
+
this.genericScheduler = new Scheduler(this.visorConfig, schedulerConfig);
|
|
268
|
+
|
|
269
|
+
// Set execution context so scheduled reminders can use the Slack client
|
|
270
|
+
this.genericScheduler.setExecutionContext({
|
|
271
|
+
slack: this.client,
|
|
272
|
+
slackClient: this.client,
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// Register Slack output adapter for posting results
|
|
276
|
+
this.genericScheduler.registerOutputAdapter(
|
|
277
|
+
createSlackOutputAdapter(this.client)
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
await this.genericScheduler.start();
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Execution Context
|
|
284
|
+
|
|
285
|
+
The scheduler uses an execution context to pass runtime dependencies to workflow executions:
|
|
286
|
+
|
|
287
|
+
- **`slackClient`**: The Slack API client for posting messages
|
|
288
|
+
- **`cliMessage`**: For simple reminders, this bypasses `human-input` prompts
|
|
289
|
+
|
|
290
|
+
### First Message Seeding
|
|
291
|
+
|
|
292
|
+
For simple reminders, the scheduler seeds the `PromptStateManager` so that `human-input` checks can consume the reminder text as if the user sent it:
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
const mgr = getPromptStateManager();
|
|
296
|
+
mgr.setFirstMessage(channel, threadTs, reminderText);
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
This ensures reminders run through chat workflows smoothly without blocking for user input.
|
|
300
|
+
|
|
301
|
+
## Natural Language Parsing
|
|
302
|
+
|
|
303
|
+
The scheduler understands various time expressions:
|
|
304
|
+
|
|
305
|
+
### One-time
|
|
306
|
+
- "in 2 hours"
|
|
307
|
+
- "in 30 minutes"
|
|
308
|
+
- "tomorrow at 9am"
|
|
309
|
+
- "next Monday at 3pm"
|
|
310
|
+
- "Friday at noon"
|
|
311
|
+
|
|
312
|
+
### Recurring
|
|
313
|
+
- "every day at 9am"
|
|
314
|
+
- "every Monday at 9am"
|
|
315
|
+
- "every weekday at 9am"
|
|
316
|
+
- "every hour"
|
|
317
|
+
- "every 30 minutes"
|
|
318
|
+
- "every month on the 1st at midnight"
|
|
319
|
+
|
|
320
|
+
## Schedule Lifecycle
|
|
321
|
+
|
|
322
|
+
1. **Created**: Schedule is stored with status `active`
|
|
323
|
+
2. **Due**: When current time >= nextRunAt, schedule is picked up
|
|
324
|
+
3. **Executing**: Workflow runs with schedule context
|
|
325
|
+
4. **Completed**:
|
|
326
|
+
- One-time: status changes to `completed`
|
|
327
|
+
- Recurring: `nextRunAt` is updated, status stays `active`
|
|
328
|
+
5. **Paused**: Schedule is skipped during checks
|
|
329
|
+
6. **Failed**: Increments `failureCount`, may be retried
|
|
330
|
+
|
|
331
|
+
## Simple Reminders (No Workflow)
|
|
332
|
+
|
|
333
|
+
When a schedule has no `workflow` specified but includes `workflowInputs.text`, it runs as a "simple reminder":
|
|
334
|
+
|
|
335
|
+
1. The reminder text is treated as if the user sent it as a new message
|
|
336
|
+
2. It runs through the full visor pipeline (all configured checks)
|
|
337
|
+
3. The AI processes it and posts the response back via the Slack frontend
|
|
338
|
+
4. The `SlackOutputAdapter` detects when the pipeline handled output and avoids double-posting
|
|
339
|
+
|
|
340
|
+
This allows reminders like "check how many Jira tickets were created this week" to get an AI-generated response rather than just echoing the reminder text.
|
|
341
|
+
|
|
342
|
+
```yaml
|
|
343
|
+
# Example: Schedule created via AI tool
|
|
344
|
+
# When this fires, it runs through the pipeline and posts the AI response
|
|
345
|
+
{
|
|
346
|
+
"workflowInputs": { "text": "How many PRs were merged today?" },
|
|
347
|
+
"outputContext": { "type": "slack", "target": "D09SZABNLG3" }
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Response Continuity (previousResponse)
|
|
352
|
+
|
|
353
|
+
For **recurring** simple reminders, the scheduler saves the AI response after each execution. On subsequent runs, the previous response is included in the context, allowing the AI to reference or build upon its earlier answer.
|
|
354
|
+
|
|
355
|
+
**How it works:**
|
|
356
|
+
1. Reminder fires and runs through the visor pipeline
|
|
357
|
+
2. AI generates a response, which is posted to Slack
|
|
358
|
+
3. The response text is saved as `previousResponse` in the schedule store
|
|
359
|
+
4. On the next run, the reminder text includes the previous response:
|
|
360
|
+
```
|
|
361
|
+
<original reminder text>
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
**Previous Response (for context):**
|
|
365
|
+
<AI's previous response>
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
Please provide an updated response based on the reminder above.
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
**Example use case:**
|
|
372
|
+
```
|
|
373
|
+
User: "Every day at 9am, tell me how many Jira tickets were created"
|
|
374
|
+
|
|
375
|
+
Day 1: AI responds with "5 tickets were created yesterday"
|
|
376
|
+
Day 2: AI sees previous response and can say "8 tickets today (up from 5 yesterday)"
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
This feature enables continuity for status updates, progress tracking, and any recurring reminder where historical context is valuable. The AI can:
|
|
380
|
+
- Compare current data to previous runs
|
|
381
|
+
- Track trends over time
|
|
382
|
+
- Provide delta/change information
|
|
383
|
+
- Reference what was said before
|
|
384
|
+
|
|
385
|
+
**Note:** One-time schedules do not save previousResponse since they only execute once.
|
|
386
|
+
|
|
387
|
+
## Architecture
|
|
388
|
+
|
|
389
|
+
### File Structure
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
src/
|
|
393
|
+
├── scheduler/ # Generic scheduler module
|
|
394
|
+
│ ├── index.ts # Public exports
|
|
395
|
+
│ ├── schedule-store.ts # JSON persistence for schedules
|
|
396
|
+
│ ├── schedule-parser.ts # Natural language parsing utilities
|
|
397
|
+
│ ├── scheduler.ts # Generic scheduler daemon
|
|
398
|
+
│ ├── schedule-tool.ts # AI tool for schedule management
|
|
399
|
+
│ └── cli-handler.ts # CLI command handlers
|
|
400
|
+
│
|
|
401
|
+
└── slack/
|
|
402
|
+
└── slack-output-adapter.ts # Posts results to Slack
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Key Components
|
|
406
|
+
|
|
407
|
+
| Component | Purpose |
|
|
408
|
+
|-----------|---------|
|
|
409
|
+
| `Scheduler` | Main daemon that checks for due schedules and executes them |
|
|
410
|
+
| `ScheduleStore` | Singleton for persisting schedules to JSON |
|
|
411
|
+
| `ScheduleOutputAdapter` | Interface for output destinations |
|
|
412
|
+
| `SlackOutputAdapter` | Implements output posting for Slack |
|
|
413
|
+
| `schedule-tool` | AI tool definition and handler |
|
|
414
|
+
|
|
415
|
+
### Execution Flow
|
|
416
|
+
|
|
417
|
+
1. User creates schedule via AI tool or CLI
|
|
418
|
+
2. `ScheduleStore.create()` persists schedule
|
|
419
|
+
3. `Scheduler` either sets up cron job (recurring) or setTimeout (one-time)
|
|
420
|
+
4. When schedule fires:
|
|
421
|
+
- With workflow: Runs named workflow via `StateMachineExecutionEngine`
|
|
422
|
+
- Without workflow: Runs reminder text through full visor pipeline
|
|
423
|
+
5. `SlackOutputAdapter.sendResult()` posts results (unless pipeline already handled it)
|
|
424
|
+
|
|
425
|
+
## Troubleshooting
|
|
426
|
+
|
|
427
|
+
### Schedule Not Running
|
|
428
|
+
|
|
429
|
+
1. Check scheduler is running: `visor schedule start`
|
|
430
|
+
2. Verify schedule status: `visor schedule list`
|
|
431
|
+
3. Check workflow exists in config
|
|
432
|
+
4. Verify permissions allow the schedule type
|
|
433
|
+
|
|
434
|
+
### Reminder Not Posting to Slack
|
|
435
|
+
|
|
436
|
+
1. Verify the execution context includes Slack client:
|
|
437
|
+
```typescript
|
|
438
|
+
scheduler.setExecutionContext({ slack: client, slackClient: client });
|
|
439
|
+
```
|
|
440
|
+
2. Check that `SlackOutputAdapter` is registered:
|
|
441
|
+
```typescript
|
|
442
|
+
scheduler.registerOutputAdapter(createSlackOutputAdapter(client));
|
|
443
|
+
```
|
|
444
|
+
3. For simple reminders, verify the pipeline has a `human-input` check and AI check
|
|
445
|
+
4. Check logs for `[SlackOutputAdapter] Skipping post` - this means the pipeline already handled output
|
|
446
|
+
|
|
447
|
+
### Personal Reminders Showing in Channel
|
|
448
|
+
|
|
449
|
+
If personal reminders appear when listing in a channel, ensure:
|
|
450
|
+
1. The `allowedScheduleType` context is being set correctly based on channel type
|
|
451
|
+
2. The schedule's `outputContext.target` correctly identifies the channel type
|
|
452
|
+
|
|
453
|
+
### Permission Denied
|
|
454
|
+
|
|
455
|
+
1. Check `permissions` config matches schedule type
|
|
456
|
+
2. Verify workflow matches `allowed_workflows` patterns
|
|
457
|
+
3. Ensure workflow doesn't match `denied_workflows`
|
|
458
|
+
|
|
459
|
+
### Timezone Issues
|
|
460
|
+
|
|
461
|
+
1. Set explicit timezone in config: `default_timezone: America/New_York`
|
|
462
|
+
2. User timezone is captured when schedule is created
|
|
463
|
+
3. All times stored as UTC internally
|
|
464
|
+
|
|
465
|
+
## API Reference
|
|
466
|
+
|
|
467
|
+
### Schedule Interface
|
|
468
|
+
|
|
469
|
+
```typescript
|
|
470
|
+
interface Schedule {
|
|
471
|
+
id: string; // UUID v4
|
|
472
|
+
creatorId: string; // User who created
|
|
473
|
+
creatorName?: string; // User display name (for messages)
|
|
474
|
+
creatorContext?: string; // "slack:U123", "github:user", "cli"
|
|
475
|
+
timezone: string; // IANA timezone
|
|
476
|
+
schedule: string; // Cron expression (empty for one-time)
|
|
477
|
+
runAt?: number; // Unix timestamp (one-time only)
|
|
478
|
+
isRecurring: boolean;
|
|
479
|
+
originalExpression: string; // Natural language input (for display)
|
|
480
|
+
workflow?: string; // Workflow/check ID (undefined for simple reminders)
|
|
481
|
+
workflowInputs?: Record<string, unknown>; // For reminders: { text: "..." }
|
|
482
|
+
outputContext?: ScheduleOutputContext;
|
|
483
|
+
status: 'active' | 'paused' | 'completed' | 'failed';
|
|
484
|
+
nextRunAt?: number;
|
|
485
|
+
lastRunAt?: number;
|
|
486
|
+
runCount: number;
|
|
487
|
+
failureCount: number;
|
|
488
|
+
lastError?: string; // Last error message if failed
|
|
489
|
+
previousResponse?: string; // AI response from last run (recurring only)
|
|
490
|
+
createdAt: number; // Creation timestamp
|
|
491
|
+
}
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
### ScheduleOutputContext
|
|
495
|
+
|
|
496
|
+
```typescript
|
|
497
|
+
interface ScheduleOutputContext {
|
|
498
|
+
type: 'slack' | 'github' | 'webhook' | 'none';
|
|
499
|
+
target?: string;
|
|
500
|
+
threadId?: string;
|
|
501
|
+
metadata?: Record<string, unknown>;
|
|
502
|
+
}
|
|
503
|
+
```
|
|
@@ -122,6 +122,11 @@ slack:
|
|
|
122
122
|
# to mention/threads/channel allowlist gating).
|
|
123
123
|
allow_bot_messages: false
|
|
124
124
|
|
|
125
|
+
# Optional: allow guest users (default: false)
|
|
126
|
+
# When false, single-channel and multi-channel guests are ignored.
|
|
127
|
+
# Set to true to allow guest users to interact with the bot.
|
|
128
|
+
allow_guests: false
|
|
129
|
+
|
|
125
130
|
# Optional: rate limiting
|
|
126
131
|
rate_limiting:
|
|
127
132
|
enabled: true
|
|
@@ -163,6 +168,7 @@ checks:
|
|
|
163
168
|
| `threads` | string | `"any"` | `"required"` to only respond in threads |
|
|
164
169
|
| `channel_allowlist` | string[] | `[]` | Limit to specific channels (supports `*` wildcard) |
|
|
165
170
|
| `allow_bot_messages` | boolean | `false` | Allow `bot_message` events to trigger runs |
|
|
171
|
+
| `allow_guests` | boolean | `false` | Allow guest users (single/multi-channel) to trigger runs |
|
|
166
172
|
| `show_raw_output` | boolean | `false` | Post raw JSON output (for debugging) |
|
|
167
173
|
| `reactions.enabled` | boolean | `true` | Enable reaction management |
|
|
168
174
|
| `reactions.ack` | string | `"eyes"` | Reaction name for acknowledgement |
|
|
@@ -468,8 +474,23 @@ Log messages include:
|
|
|
468
474
|
- `[slack-frontend]` - Message posting and reactions
|
|
469
475
|
- `[prompt-state]` - Human input state management
|
|
470
476
|
|
|
477
|
+
## Scheduled Reminders
|
|
478
|
+
|
|
479
|
+
The scheduler integrates with Slack to deliver scheduled reminders and workflow results. See [Scheduler](./scheduler.md) for full documentation.
|
|
480
|
+
|
|
481
|
+
Quick example:
|
|
482
|
+
```
|
|
483
|
+
User: "remind me to check PRs every day at 9am"
|
|
484
|
+
Bot: Schedule created! Will remind you every day at 9am.
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
When the schedule fires:
|
|
488
|
+
1. For simple reminders: The text runs through the visor pipeline, and the AI response is posted back
|
|
489
|
+
2. For workflow schedules: The workflow executes and results are posted via `SlackOutputAdapter`
|
|
490
|
+
|
|
471
491
|
## Related Documentation
|
|
472
492
|
|
|
493
|
+
- [Scheduler](./scheduler.md) - Schedule workflows and reminders
|
|
473
494
|
- [Human Input Provider](./human-input-provider.md) - Detailed documentation on the `human-input` check type
|
|
474
495
|
- [Bot Transports RFC](./bot-transports-rfc.md) - Technical design document for Slack integration
|
|
475
496
|
- [Recipes](./recipes.md) - Common workflow patterns including chat loops
|
package/dist/docs/timeouts.md
CHANGED
|
@@ -140,7 +140,7 @@ The CLI supports a global timeout via the `--timeout` flag:
|
|
|
140
140
|
visor --check all --timeout 300000 # 5 minute global timeout (milliseconds)
|
|
141
141
|
```
|
|
142
142
|
|
|
143
|
-
This timeout applies to AI operations. The default is 1200000ms (
|
|
143
|
+
This timeout applies to AI operations. The default is 1200000ms (30 minutes).
|
|
144
144
|
|
|
145
145
|
## Examples
|
|
146
146
|
|
|
@@ -246,6 +246,12 @@ steps:
|
|
|
246
246
|
|
|
247
247
|
Output structure: `{ text: string, ts: number }`
|
|
248
248
|
|
|
249
|
+
> **Tip:** Use `--tui` mode for interactive prompts and real-time visualization:
|
|
250
|
+
> ```bash
|
|
251
|
+
> visor --tui --config workflow.yaml
|
|
252
|
+
> ```
|
|
253
|
+
> TUI provides a chat-style interface for human-input prompts. See [Interactive TUI Mode](#interactive-tui-mode).
|
|
254
|
+
|
|
249
255
|
### 5. Log Check (`type: log`)
|
|
250
256
|
|
|
251
257
|
Output messages to the console/log. Useful for debugging workflows and displaying execution information.
|
|
@@ -1333,6 +1339,39 @@ visor test --validate
|
|
|
1333
1339
|
visor --config workflow.yaml --event pr_opened
|
|
1334
1340
|
```
|
|
1335
1341
|
|
|
1342
|
+
### Interactive TUI Mode
|
|
1343
|
+
|
|
1344
|
+
TUI mode provides a persistent terminal interface for running any workflow:
|
|
1345
|
+
|
|
1346
|
+
```bash
|
|
1347
|
+
# Start interactive TUI
|
|
1348
|
+
visor --tui --config workflow.yaml
|
|
1349
|
+
|
|
1350
|
+
# TUI with debug logging
|
|
1351
|
+
visor --tui --config workflow.yaml --debug
|
|
1352
|
+
```
|
|
1353
|
+
|
|
1354
|
+
**TUI Tabs:**
|
|
1355
|
+
- **Chat (1)**: Interactive prompts and workflow results
|
|
1356
|
+
- **Logs (2)**: Execution logs and debug output
|
|
1357
|
+
- **Traces (3)**: Real-time OpenTelemetry execution tree
|
|
1358
|
+
|
|
1359
|
+
**Key Bindings:**
|
|
1360
|
+
| Key | Action |
|
|
1361
|
+
|-----|--------|
|
|
1362
|
+
| `Shift+Tab` | Cycle between tabs |
|
|
1363
|
+
| `1` / `2` / `3` | Jump to Chat / Logs / Traces |
|
|
1364
|
+
| `e` | Toggle engine states in Traces tab |
|
|
1365
|
+
| `Enter` | Submit input |
|
|
1366
|
+
| `Ctrl+C` | Abort workflow |
|
|
1367
|
+
| `q` | Exit (when complete) |
|
|
1368
|
+
|
|
1369
|
+
The Traces tab shows:
|
|
1370
|
+
- Execution tree with check hierarchy
|
|
1371
|
+
- forEach iterations grouped under parent
|
|
1372
|
+
- IN/OUT/ERR lines for each span
|
|
1373
|
+
- Press `e` to show/hide engine internals (LevelDispatch, WavePlanning)
|
|
1374
|
+
|
|
1336
1375
|
---
|
|
1337
1376
|
|
|
1338
1377
|
## Related Documentation
|
package/dist/examples/README.md
CHANGED
|
@@ -126,6 +126,14 @@ Example configurations demonstrating various Visor features and use cases.
|
|
|
126
126
|
- **`failure-conditions-github-style.yaml`** - GitHub-style failure conditions
|
|
127
127
|
- **`failure-conditions-migration.yaml`** - Migration patterns for failure conditions
|
|
128
128
|
|
|
129
|
+
### Sandbox Examples
|
|
130
|
+
- **`sandbox-basic.yaml`** - Basic Docker sandbox with image mode
|
|
131
|
+
- **`sandbox-cache.yaml`** - Sandbox with cache volume mounts
|
|
132
|
+
- **`sandbox-dockerfile-inline.yaml`** - Sandbox with inline Dockerfile
|
|
133
|
+
- **`sandbox-env-passthrough.yaml`** - Sandbox environment variable passthrough
|
|
134
|
+
- **`sandbox-multi-env.yaml`** - Multiple sandbox environments per check
|
|
135
|
+
- **`sandbox-read-only.yaml`** - Read-only sandbox with network isolation
|
|
136
|
+
|
|
129
137
|
### Integration Examples
|
|
130
138
|
- **`jira-simple-example.yaml`** - Simple JIRA integration
|
|
131
139
|
- **`jira-single-issue-workflow.yaml`** - Single JIRA issue workflow
|
|
@@ -406,6 +414,28 @@ visor --config examples/bedrock-config.yaml --provider bedrock
|
|
|
406
414
|
visor --config examples/claude-code-config.yaml
|
|
407
415
|
```
|
|
408
416
|
|
|
417
|
+
## 🐳 Sandbox Examples
|
|
418
|
+
|
|
419
|
+
```bash
|
|
420
|
+
# Basic Docker sandbox
|
|
421
|
+
visor --config examples/sandbox-basic.yaml
|
|
422
|
+
|
|
423
|
+
# Sandbox with cache volumes
|
|
424
|
+
visor --config examples/sandbox-cache.yaml
|
|
425
|
+
|
|
426
|
+
# Inline Dockerfile sandbox
|
|
427
|
+
visor --config examples/sandbox-dockerfile-inline.yaml
|
|
428
|
+
|
|
429
|
+
# Environment variable passthrough
|
|
430
|
+
visor --config examples/sandbox-env-passthrough.yaml
|
|
431
|
+
|
|
432
|
+
# Multiple sandbox environments
|
|
433
|
+
visor --config examples/sandbox-multi-env.yaml
|
|
434
|
+
|
|
435
|
+
# Read-only sandbox with network isolation
|
|
436
|
+
visor --config examples/sandbox-read-only.yaml
|
|
437
|
+
```
|
|
438
|
+
|
|
409
439
|
## 🔧 MCP & Tools Examples
|
|
410
440
|
|
|
411
441
|
```bash
|
|
@@ -38,7 +38,7 @@ checks:
|
|
|
38
38
|
operation: set
|
|
39
39
|
namespace: calculator
|
|
40
40
|
key: number1
|
|
41
|
-
value_js: "parseFloat(outputs['get-number1'])"
|
|
41
|
+
value_js: "parseFloat(outputs['get-number1'].text)"
|
|
42
42
|
|
|
43
43
|
# Step 3: Get second number
|
|
44
44
|
get-number2:
|
|
@@ -55,7 +55,7 @@ checks:
|
|
|
55
55
|
operation: set
|
|
56
56
|
namespace: calculator
|
|
57
57
|
key: number2
|
|
58
|
-
value_js: "parseFloat(outputs['get-number2'])"
|
|
58
|
+
value_js: "parseFloat(outputs['get-number2'].text)"
|
|
59
59
|
|
|
60
60
|
# Step 5: Get operation
|
|
61
61
|
get-operation:
|
|
@@ -72,7 +72,7 @@ checks:
|
|
|
72
72
|
operation: set
|
|
73
73
|
namespace: calculator
|
|
74
74
|
key: operation
|
|
75
|
-
value_js: "outputs['get-operation'].trim()"
|
|
75
|
+
value_js: "outputs['get-operation'].text.trim()"
|
|
76
76
|
|
|
77
77
|
# Step 7: Perform calculation using memory and JavaScript
|
|
78
78
|
calculate:
|
|
@@ -122,7 +122,7 @@ checks:
|
|
|
122
122
|
║ CALCULATION RESULT ║
|
|
123
123
|
╠════════════════════════════════════════╣
|
|
124
124
|
║ ║
|
|
125
|
-
║ {{ outputs['get-number1'] }} {{ outputs['get-operation'] }} {{ outputs['get-number2'] }} = {{ outputs['calculate'] }}
|
|
125
|
+
║ {{ outputs['get-number1'].text }} {{ outputs['get-operation'].text }} {{ outputs['get-number2'].text }} = {{ outputs['calculate'] }}
|
|
126
126
|
║ ║
|
|
127
127
|
╚════════════════════════════════════════╝
|
|
128
128
|
|