milaidy 1.0.0
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/LICENSE +8 -0
- package/README.md +538 -0
- package/dist/argv-CfSowvEA.js +63 -0
- package/dist/config-B-mboG4v.js +4 -0
- package/dist/eliza-CPJjgw-e.js +1491 -0
- package/dist/eliza.js +2192 -0
- package/dist/entry.js +232 -0
- package/dist/index.js +209 -0
- package/dist/links-BFKlWqSe.js +15 -0
- package/dist/paths-D_yh1DEJ.js +69 -0
- package/dist/plugins-cli-B7kSre2c.js +134 -0
- package/dist/program-6KwWwKKh.js +510 -0
- package/dist/register.agents-CPVmSjMG.js +17 -0
- package/dist/register.browser-B2ooXxNx.js +15 -0
- package/dist/register.channels-CMYQ6K6Y.js +42 -0
- package/dist/register.cron-D91lY1_Y.js +9 -0
- package/dist/register.devices-rU5I5L_y.js +13 -0
- package/dist/register.gateway-82SLAvw3.js +22 -0
- package/dist/register.hooks-B_XTBEkt.js +9 -0
- package/dist/register.logs-BgEGcPd8.js +10 -0
- package/dist/register.models-BJt9eVgZ.js +26 -0
- package/dist/register.nodes-B5xY1s8a.js +9 -0
- package/dist/register.skills-SFQqYIhg.js +10 -0
- package/dist/register.subclis-uF_AsbWR.js +187 -0
- package/dist/run-main-XODklzS-.js +56 -0
- package/dist/theme-DBvtuGeq.js +36 -0
- package/dist/utils-C1AUpp_V.js +42 -0
- package/dist/version-Cpn3yr5D.js +26 -0
- package/dist/workspace-Co3Wul2D.js +206 -0
- package/dist/workspace-DCA6MNVK.js +350 -0
- package/docs/.i18n/README.md +31 -0
- package/docs/.i18n/glossary.zh-CN.json +210 -0
- package/docs/.i18n/zh-CN.tm.jsonl +1329 -0
- package/docs/CNAME +1 -0
- package/docs/automation/cron-jobs.md +468 -0
- package/docs/automation/cron-vs-heartbeat.md +254 -0
- package/docs/automation/gmail-pubsub.md +256 -0
- package/docs/automation/poll.md +69 -0
- package/docs/automation/webhook.md +163 -0
- package/docs/bedrock.md +176 -0
- package/docs/brave-search.md +41 -0
- package/docs/broadcast-groups.md +442 -0
- package/docs/cli/acp.md +170 -0
- package/docs/cli/agent.md +24 -0
- package/docs/cli/agents.md +75 -0
- package/docs/cli/approvals.md +50 -0
- package/docs/cli/browser.md +107 -0
- package/docs/cli/channels.md +79 -0
- package/docs/cli/config.md +50 -0
- package/docs/cli/configure.md +33 -0
- package/docs/cli/cron.md +42 -0
- package/docs/cli/dashboard.md +16 -0
- package/docs/cli/devices.md +67 -0
- package/docs/cli/directory.md +63 -0
- package/docs/cli/dns.md +23 -0
- package/docs/cli/docs.md +15 -0
- package/docs/cli/doctor.md +41 -0
- package/docs/cli/gateway.md +199 -0
- package/docs/cli/health.md +21 -0
- package/docs/cli/hooks.md +291 -0
- package/docs/cli/index.md +1029 -0
- package/docs/cli/logs.md +24 -0
- package/docs/cli/memory.md +45 -0
- package/docs/cli/message.md +239 -0
- package/docs/cli/models.md +79 -0
- package/docs/cli/node.md +112 -0
- package/docs/cli/nodes.md +73 -0
- package/docs/cli/onboard.md +29 -0
- package/docs/cli/pairing.md +21 -0
- package/docs/cli/plugins.md +62 -0
- package/docs/cli/reset.md +17 -0
- package/docs/cli/sandbox.md +152 -0
- package/docs/cli/security.md +26 -0
- package/docs/cli/sessions.md +16 -0
- package/docs/cli/setup.md +29 -0
- package/docs/cli/skills.md +26 -0
- package/docs/cli/status.md +26 -0
- package/docs/cli/system.md +60 -0
- package/docs/cli/tui.md +23 -0
- package/docs/cli/uninstall.md +17 -0
- package/docs/cli/update.md +98 -0
- package/docs/cli/voicecall.md +34 -0
- package/docs/cli/webhooks.md +25 -0
- package/docs/concepts/agent-loop.md +146 -0
- package/docs/concepts/agent-workspace.md +229 -0
- package/docs/concepts/agent.md +122 -0
- package/docs/concepts/architecture.md +129 -0
- package/docs/concepts/channel-routing.md +114 -0
- package/docs/concepts/compaction.md +61 -0
- package/docs/concepts/context.md +159 -0
- package/docs/concepts/features.md +53 -0
- package/docs/concepts/group-messages.md +84 -0
- package/docs/concepts/groups.md +373 -0
- package/docs/concepts/markdown-formatting.md +130 -0
- package/docs/concepts/memory.md +546 -0
- package/docs/concepts/messages.md +154 -0
- package/docs/concepts/model-failover.md +149 -0
- package/docs/concepts/model-providers.md +315 -0
- package/docs/concepts/models.md +208 -0
- package/docs/concepts/multi-agent.md +376 -0
- package/docs/concepts/oauth.md +145 -0
- package/docs/concepts/plugins.md +454 -0
- package/docs/concepts/presence.md +102 -0
- package/docs/concepts/queue.md +89 -0
- package/docs/concepts/retry.md +69 -0
- package/docs/concepts/secrets.md +300 -0
- package/docs/concepts/session-pruning.md +122 -0
- package/docs/concepts/session-tool.md +193 -0
- package/docs/concepts/session.md +188 -0
- package/docs/concepts/sessions.md +10 -0
- package/docs/concepts/skills.md +392 -0
- package/docs/concepts/streaming.md +135 -0
- package/docs/concepts/system-prompt.md +114 -0
- package/docs/concepts/timezone.md +91 -0
- package/docs/concepts/typebox.md +289 -0
- package/docs/concepts/typing-indicators.md +68 -0
- package/docs/concepts/usage-tracking.md +35 -0
- package/docs/custom.css +4 -0
- package/docs/date-time.md +128 -0
- package/docs/debugging.md +162 -0
- package/docs/docs.json +1599 -0
- package/docs/environment.md +81 -0
- package/docs/hooks.md +876 -0
- package/docs/index.md +179 -0
- package/docs/install/ansible.md +208 -0
- package/docs/install/bun.md +59 -0
- package/docs/install/development-channels.md +75 -0
- package/docs/install/docker.md +567 -0
- package/docs/install/index.md +185 -0
- package/docs/install/installer.md +123 -0
- package/docs/install/migrating.md +192 -0
- package/docs/install/nix.md +96 -0
- package/docs/install/node.md +78 -0
- package/docs/install/uninstall.md +128 -0
- package/docs/install/updating.md +228 -0
- package/docs/logging.md +350 -0
- package/docs/multi-agent-sandbox-tools.md +395 -0
- package/docs/network.md +54 -0
- package/docs/nodes/audio.md +114 -0
- package/docs/nodes/camera.md +156 -0
- package/docs/nodes/images.md +72 -0
- package/docs/nodes/index.md +341 -0
- package/docs/nodes/location-command.md +113 -0
- package/docs/nodes/media-understanding.md +379 -0
- package/docs/nodes/talk.md +90 -0
- package/docs/nodes/voicewake.md +65 -0
- package/docs/northflank.mdx +53 -0
- package/docs/perplexity.md +80 -0
- package/docs/platforms/android.md +129 -0
- package/docs/platforms/digitalocean.md +262 -0
- package/docs/platforms/exe-dev.md +125 -0
- package/docs/platforms/fly.md +486 -0
- package/docs/platforms/gcp.md +503 -0
- package/docs/platforms/hetzner.md +330 -0
- package/docs/platforms/index.md +53 -0
- package/docs/platforms/ios.md +106 -0
- package/docs/platforms/linux.md +94 -0
- package/docs/platforms/mac/bundled-gateway.md +73 -0
- package/docs/platforms/mac/canvas.md +125 -0
- package/docs/platforms/mac/child-process.md +69 -0
- package/docs/platforms/mac/dev-setup.md +102 -0
- package/docs/platforms/mac/health.md +34 -0
- package/docs/platforms/mac/icon.md +31 -0
- package/docs/platforms/mac/logging.md +57 -0
- package/docs/platforms/mac/menu-bar.md +81 -0
- package/docs/platforms/mac/peekaboo.md +65 -0
- package/docs/platforms/mac/permissions.md +44 -0
- package/docs/platforms/mac/release.md +85 -0
- package/docs/platforms/mac/remote.md +83 -0
- package/docs/platforms/mac/signing.md +47 -0
- package/docs/platforms/mac/skills.md +33 -0
- package/docs/platforms/mac/voice-overlay.md +60 -0
- package/docs/platforms/mac/voicewake.md +67 -0
- package/docs/platforms/mac/webchat.md +41 -0
- package/docs/platforms/mac/xpc.md +61 -0
- package/docs/platforms/macos-vm.md +281 -0
- package/docs/platforms/macos.md +203 -0
- package/docs/platforms/oracle.md +303 -0
- package/docs/platforms/raspberry-pi.md +358 -0
- package/docs/platforms/windows.md +159 -0
- package/docs/plugin.md +651 -0
- package/docs/plugins/agent-tools.md +99 -0
- package/docs/plugins/manifest.md +71 -0
- package/docs/plugins/voice-call.md +273 -0
- package/docs/plugins/zalouser.md +70 -0
- package/docs/providers/anthropic.md +152 -0
- package/docs/providers/claude-max-api-proxy.md +148 -0
- package/docs/providers/cloudflare-ai-gateway.md +71 -0
- package/docs/providers/deepgram.md +93 -0
- package/docs/providers/glm.md +33 -0
- package/docs/providers/index.md +63 -0
- package/docs/providers/minimax.md +208 -0
- package/docs/providers/models.md +51 -0
- package/docs/providers/moonshot.md +142 -0
- package/docs/providers/ollama.md +223 -0
- package/docs/providers/openai.md +62 -0
- package/docs/providers/opencode.md +36 -0
- package/docs/providers/openrouter.md +37 -0
- package/docs/providers/qwen.md +53 -0
- package/docs/providers/synthetic.md +99 -0
- package/docs/providers/venice.md +267 -0
- package/docs/providers/vercel-ai-gateway.md +50 -0
- package/docs/providers/xiaomi.md +64 -0
- package/docs/providers/zai.md +36 -0
- package/docs/railway.mdx +99 -0
- package/docs/reference/templates/AGENTS.md +9 -0
- package/docs/reference/templates/BOOTSTRAP.md +3 -0
- package/docs/reference/templates/HEARTBEAT.md +3 -0
- package/docs/reference/templates/IDENTITY.md +3 -0
- package/docs/reference/templates/TOOLS.md +3 -0
- package/docs/reference/templates/USER.md +3 -0
- package/docs/render.mdx +165 -0
- package/docs/start/docs-directory.md +63 -0
- package/docs/start/getting-started.md +212 -0
- package/docs/start/milaidy.md +247 -0
- package/docs/start/onboarding.md +258 -0
- package/docs/start/pairing.md +86 -0
- package/docs/start/quickstart.md +81 -0
- package/docs/start/setup.md +149 -0
- package/docs/start/showcase.md +416 -0
- package/docs/start/wizard.md +418 -0
- package/docs/testing.md +368 -0
- package/docs/token-use.md +112 -0
- package/docs/tools/agent-send.md +53 -0
- package/docs/tools/apply-patch.md +50 -0
- package/docs/tools/browser-linux-troubleshooting.md +139 -0
- package/docs/tools/browser-login.md +68 -0
- package/docs/tools/browser.md +576 -0
- package/docs/tools/chrome-extension.md +178 -0
- package/docs/tools/clawhub.md +257 -0
- package/docs/tools/creating-skills.md +54 -0
- package/docs/tools/elevated.md +57 -0
- package/docs/tools/exec-approvals.md +246 -0
- package/docs/tools/exec.md +179 -0
- package/docs/tools/firecrawl.md +61 -0
- package/docs/tools/index.md +508 -0
- package/docs/tools/llm-task.md +115 -0
- package/docs/tools/reactions.md +22 -0
- package/docs/tools/skills-config.md +76 -0
- package/docs/tools/skills.md +300 -0
- package/docs/tools/slash-commands.md +196 -0
- package/docs/tools/subagents.md +151 -0
- package/docs/tools/thinking.md +73 -0
- package/docs/tools/web.md +261 -0
- package/docs/tui.md +159 -0
- package/docs/vps.md +43 -0
- package/docs/web/control-ui.md +221 -0
- package/docs/web/dashboard.md +46 -0
- package/docs/web/index.md +116 -0
- package/docs/web/webchat.md +49 -0
- package/milaidy.mjs +14 -0
- package/package.json +271 -0
- package/skills/.cache/catalog.json +88519 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Guidance for choosing between heartbeat and cron jobs for automation"
|
|
3
|
+
read_when:
|
|
4
|
+
- Deciding how to schedule recurring tasks
|
|
5
|
+
- Setting up background monitoring or notifications
|
|
6
|
+
- Optimizing token usage for periodic checks
|
|
7
|
+
title: "Cron vs Heartbeat"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Cron vs Heartbeat: When to Use Each
|
|
11
|
+
|
|
12
|
+
Both heartbeats and cron jobs let you run tasks on a schedule. This guide helps you choose the right mechanism for your use case.
|
|
13
|
+
|
|
14
|
+
## Quick Decision Guide
|
|
15
|
+
|
|
16
|
+
| Use Case | Recommended | Why |
|
|
17
|
+
| ------------------------------------ | ------------------- | ---------------------------------------- |
|
|
18
|
+
| Check inbox every 30 min | Heartbeat | Batches with other checks, context-aware |
|
|
19
|
+
| Send daily report at 9am sharp | Cron (isolated) | Exact timing needed |
|
|
20
|
+
| Monitor calendar for upcoming events | Heartbeat | Natural fit for periodic awareness |
|
|
21
|
+
| Run weekly deep analysis | Cron (isolated) | Standalone task, can use different model |
|
|
22
|
+
| Remind me in 20 minutes | Cron (main, `--at`) | One-shot with precise timing |
|
|
23
|
+
| Background project health check | Heartbeat | Piggybacks on existing cycle |
|
|
24
|
+
|
|
25
|
+
## Heartbeat: Periodic Awareness
|
|
26
|
+
|
|
27
|
+
Heartbeats run in the **main session** at a regular interval (default: 30 min). They're designed for the agent to check on things and surface anything important.
|
|
28
|
+
|
|
29
|
+
### When to use heartbeat
|
|
30
|
+
|
|
31
|
+
- **Multiple periodic checks**: Instead of 5 separate cron jobs checking inbox, calendar, weather, notifications, and project status, a single heartbeat can batch all of these.
|
|
32
|
+
- **Context-aware decisions**: The agent has full main-session context, so it can make smart decisions about what's urgent vs. what can wait.
|
|
33
|
+
- **Conversational continuity**: Heartbeat runs share the same session, so the agent remembers recent conversations and can follow up naturally.
|
|
34
|
+
- **Low-overhead monitoring**: One heartbeat replaces many small polling tasks.
|
|
35
|
+
|
|
36
|
+
### Heartbeat advantages
|
|
37
|
+
|
|
38
|
+
- **Batches multiple checks**: One agent turn can review inbox, calendar, and notifications together.
|
|
39
|
+
- **Reduces API calls**: A single heartbeat is cheaper than 5 isolated cron jobs.
|
|
40
|
+
- **Context-aware**: The agent knows what you've been working on and can prioritize accordingly.
|
|
41
|
+
- **Smart suppression**: If nothing needs attention, the agent replies `HEARTBEAT_OK` and no message is delivered.
|
|
42
|
+
- **Natural timing**: Drifts slightly based on queue load, which is fine for most monitoring.
|
|
43
|
+
|
|
44
|
+
### Heartbeat example: HEARTBEAT.md checklist
|
|
45
|
+
|
|
46
|
+
```md
|
|
47
|
+
# Heartbeat checklist
|
|
48
|
+
|
|
49
|
+
- Check email for urgent messages
|
|
50
|
+
- Review calendar for events in next 2 hours
|
|
51
|
+
- If a background task finished, summarize results
|
|
52
|
+
- If idle for 8+ hours, send a brief check-in
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The agent reads this on each heartbeat and handles all items in one turn.
|
|
56
|
+
|
|
57
|
+
### Configuring heartbeat
|
|
58
|
+
|
|
59
|
+
```json5
|
|
60
|
+
{
|
|
61
|
+
agents: {
|
|
62
|
+
defaults: {
|
|
63
|
+
heartbeat: {
|
|
64
|
+
every: "30m", // interval
|
|
65
|
+
target: "last", // where to deliver alerts
|
|
66
|
+
activeHours: { start: "08:00", end: "22:00" }, // optional
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
See [Heartbeat](/gateway/heartbeat) for full configuration.
|
|
74
|
+
|
|
75
|
+
## Cron: Precise Scheduling
|
|
76
|
+
|
|
77
|
+
Cron jobs run at **exact times** and can run in isolated sessions without affecting main context.
|
|
78
|
+
|
|
79
|
+
### When to use cron
|
|
80
|
+
|
|
81
|
+
- **Exact timing required**: "Send this at 9:00 AM every Monday" (not "sometime around 9").
|
|
82
|
+
- **Standalone tasks**: Tasks that don't need conversational context.
|
|
83
|
+
- **Different model/thinking**: Heavy analysis that warrants a more powerful model.
|
|
84
|
+
- **One-shot reminders**: "Remind me in 20 minutes" with `--at`.
|
|
85
|
+
- **Noisy/frequent tasks**: Tasks that would clutter main session history.
|
|
86
|
+
- **External triggers**: Tasks that should run independently of whether the agent is otherwise active.
|
|
87
|
+
|
|
88
|
+
### Cron advantages
|
|
89
|
+
|
|
90
|
+
- **Exact timing**: 5-field cron expressions with timezone support.
|
|
91
|
+
- **Session isolation**: Runs in `cron:<jobId>` without polluting main history.
|
|
92
|
+
- **Model overrides**: Use a cheaper or more powerful model per job.
|
|
93
|
+
- **Delivery control**: Isolated jobs default to `announce` (summary); choose `none` as needed.
|
|
94
|
+
- **Immediate delivery**: Announce mode posts directly without waiting for heartbeat.
|
|
95
|
+
- **No agent context needed**: Runs even if main session is idle or compacted.
|
|
96
|
+
- **One-shot support**: `--at` for precise future timestamps.
|
|
97
|
+
|
|
98
|
+
### Cron example: Daily morning briefing
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
milaidy cron add \
|
|
102
|
+
--name "Morning briefing" \
|
|
103
|
+
--cron "0 7 * * *" \
|
|
104
|
+
--tz "America/New_York" \
|
|
105
|
+
--session isolated \
|
|
106
|
+
--message "Generate today's briefing: weather, calendar, top emails, news summary." \
|
|
107
|
+
--model opus \
|
|
108
|
+
--announce \
|
|
109
|
+
--channel whatsapp \
|
|
110
|
+
--to "+15551234567"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
This runs at exactly 7:00 AM New York time, uses Opus for quality, and announces a summary directly to WhatsApp.
|
|
114
|
+
|
|
115
|
+
### Cron example: One-shot reminder
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
milaidy cron add \
|
|
119
|
+
--name "Meeting reminder" \
|
|
120
|
+
--at "20m" \
|
|
121
|
+
--session main \
|
|
122
|
+
--system-event "Reminder: standup meeting starts in 10 minutes." \
|
|
123
|
+
--wake now \
|
|
124
|
+
--delete-after-run
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
See [Cron jobs](/automation/cron-jobs) for full CLI reference.
|
|
128
|
+
|
|
129
|
+
## Decision Flowchart
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
Does the task need to run at an EXACT time?
|
|
133
|
+
YES -> Use cron
|
|
134
|
+
NO -> Continue...
|
|
135
|
+
|
|
136
|
+
Does the task need isolation from main session?
|
|
137
|
+
YES -> Use cron (isolated)
|
|
138
|
+
NO -> Continue...
|
|
139
|
+
|
|
140
|
+
Can this task be batched with other periodic checks?
|
|
141
|
+
YES -> Use heartbeat (add to HEARTBEAT.md)
|
|
142
|
+
NO -> Use cron
|
|
143
|
+
|
|
144
|
+
Is this a one-shot reminder?
|
|
145
|
+
YES -> Use cron with --at
|
|
146
|
+
NO -> Continue...
|
|
147
|
+
|
|
148
|
+
Does it need a different model or thinking level?
|
|
149
|
+
YES -> Use cron (isolated) with --model/--thinking
|
|
150
|
+
NO -> Use heartbeat
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Combining Both
|
|
154
|
+
|
|
155
|
+
The most efficient setup uses **both**:
|
|
156
|
+
|
|
157
|
+
1. **Heartbeat** handles routine monitoring (inbox, calendar, notifications) in one batched turn every 30 minutes.
|
|
158
|
+
2. **Cron** handles precise schedules (daily reports, weekly reviews) and one-shot reminders.
|
|
159
|
+
|
|
160
|
+
### Example: Efficient automation setup
|
|
161
|
+
|
|
162
|
+
**HEARTBEAT.md** (checked every 30 min):
|
|
163
|
+
|
|
164
|
+
```md
|
|
165
|
+
# Heartbeat checklist
|
|
166
|
+
|
|
167
|
+
- Scan inbox for urgent emails
|
|
168
|
+
- Check calendar for events in next 2h
|
|
169
|
+
- Review any pending tasks
|
|
170
|
+
- Light check-in if quiet for 8+ hours
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Cron jobs** (precise timing):
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# Daily morning briefing at 7am
|
|
177
|
+
milaidy cron add --name "Morning brief" --cron "0 7 * * *" --session isolated --message "..." --announce
|
|
178
|
+
|
|
179
|
+
# Weekly project review on Mondays at 9am
|
|
180
|
+
milaidy cron add --name "Weekly review" --cron "0 9 * * 1" --session isolated --message "..." --model opus
|
|
181
|
+
|
|
182
|
+
# One-shot reminder
|
|
183
|
+
milaidy cron add --name "Call back" --at "2h" --session main --system-event "Call back the client" --wake now
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Main Session vs Isolated Session
|
|
187
|
+
|
|
188
|
+
Both heartbeat and cron can interact with the main session, but differently:
|
|
189
|
+
|
|
190
|
+
| | Heartbeat | Cron (main) | Cron (isolated) |
|
|
191
|
+
| ------- | ------------------------------- | ------------------------ | -------------------------- |
|
|
192
|
+
| Session | Main | Main (via system event) | `cron:<jobId>` |
|
|
193
|
+
| History | Shared | Shared | Fresh each run |
|
|
194
|
+
| Context | Full | Full | None (starts clean) |
|
|
195
|
+
| Model | Main session model | Main session model | Can override |
|
|
196
|
+
| Output | Delivered if not `HEARTBEAT_OK` | Heartbeat prompt + event | Announce summary (default) |
|
|
197
|
+
|
|
198
|
+
### When to use main session cron
|
|
199
|
+
|
|
200
|
+
Use `--session main` with `--system-event` when you want:
|
|
201
|
+
|
|
202
|
+
- The reminder/event to appear in main session context
|
|
203
|
+
- The agent to handle it during the next heartbeat with full context
|
|
204
|
+
- No separate isolated run
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
milaidy cron add \
|
|
208
|
+
--name "Check project" \
|
|
209
|
+
--every "4h" \
|
|
210
|
+
--session main \
|
|
211
|
+
--system-event "Time for a project health check" \
|
|
212
|
+
--wake now
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### When to use isolated cron
|
|
216
|
+
|
|
217
|
+
Use `--session isolated` when you want:
|
|
218
|
+
|
|
219
|
+
- A clean slate without prior context
|
|
220
|
+
- Different model or thinking settings
|
|
221
|
+
- Announce summaries directly to a channel
|
|
222
|
+
- History that doesn't clutter main session
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
milaidy cron add \
|
|
226
|
+
--name "Deep analysis" \
|
|
227
|
+
--cron "0 6 * * 0" \
|
|
228
|
+
--session isolated \
|
|
229
|
+
--message "Weekly codebase analysis..." \
|
|
230
|
+
--model opus \
|
|
231
|
+
--thinking high \
|
|
232
|
+
--announce
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Cost Considerations
|
|
236
|
+
|
|
237
|
+
| Mechanism | Cost Profile |
|
|
238
|
+
| --------------- | ------------------------------------------------------- |
|
|
239
|
+
| Heartbeat | One turn every N minutes; scales with HEARTBEAT.md size |
|
|
240
|
+
| Cron (main) | Adds event to next heartbeat (no isolated turn) |
|
|
241
|
+
| Cron (isolated) | Full agent turn per job; can use cheaper model |
|
|
242
|
+
|
|
243
|
+
**Tips**:
|
|
244
|
+
|
|
245
|
+
- Keep `HEARTBEAT.md` small to minimize token overhead.
|
|
246
|
+
- Batch similar checks into heartbeat instead of multiple cron jobs.
|
|
247
|
+
- Use `target: "none"` on heartbeat if you only want internal processing.
|
|
248
|
+
- Use isolated cron with a cheaper model for routine tasks.
|
|
249
|
+
|
|
250
|
+
## Related
|
|
251
|
+
|
|
252
|
+
- [Heartbeat](/gateway/heartbeat) - full heartbeat configuration
|
|
253
|
+
- [Cron jobs](/automation/cron-jobs) - full cron CLI and API reference
|
|
254
|
+
- [System](/cli/system) - system events + heartbeat controls
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Gmail Pub/Sub push wired into Milaidy webhooks via gogcli"
|
|
3
|
+
read_when:
|
|
4
|
+
- Wiring Gmail inbox triggers to Milaidy
|
|
5
|
+
- Setting up Pub/Sub push for agent wake
|
|
6
|
+
title: "Gmail PubSub"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Gmail Pub/Sub -> Milaidy
|
|
10
|
+
|
|
11
|
+
Goal: Gmail watch -> Pub/Sub push -> `gog gmail watch serve` -> Milaidy webhook.
|
|
12
|
+
|
|
13
|
+
## Prereqs
|
|
14
|
+
|
|
15
|
+
- `gcloud` installed and logged in ([install guide](https://docs.cloud.google.com/sdk/docs/install-sdk)).
|
|
16
|
+
- `gog` (gogcli) installed and authorized for the Gmail account ([gogcli.sh](https://gogcli.sh/)).
|
|
17
|
+
- Milaidy hooks enabled (see [Webhooks](/automation/webhook)).
|
|
18
|
+
- `tailscale` logged in ([tailscale.com](https://tailscale.com/)). Supported setup uses Tailscale Funnel for the public HTTPS endpoint.
|
|
19
|
+
Other tunnel services can work, but are DIY/unsupported and require manual wiring.
|
|
20
|
+
Right now, Tailscale is what we support.
|
|
21
|
+
|
|
22
|
+
Example hook config (enable Gmail preset mapping):
|
|
23
|
+
|
|
24
|
+
```json5
|
|
25
|
+
{
|
|
26
|
+
hooks: {
|
|
27
|
+
enabled: true,
|
|
28
|
+
token: "MILAIDY_HOOK_TOKEN",
|
|
29
|
+
path: "/hooks",
|
|
30
|
+
presets: ["gmail"],
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
To deliver the Gmail summary to a chat surface, override the preset with a mapping
|
|
36
|
+
that sets `deliver` + optional `channel`/`to`:
|
|
37
|
+
|
|
38
|
+
```json5
|
|
39
|
+
{
|
|
40
|
+
hooks: {
|
|
41
|
+
enabled: true,
|
|
42
|
+
token: "MILAIDY_HOOK_TOKEN",
|
|
43
|
+
presets: ["gmail"],
|
|
44
|
+
mappings: [
|
|
45
|
+
{
|
|
46
|
+
match: { path: "gmail" },
|
|
47
|
+
action: "agent",
|
|
48
|
+
wakeMode: "now",
|
|
49
|
+
name: "Gmail",
|
|
50
|
+
sessionKey: "hook:gmail:{{messages[0].id}}",
|
|
51
|
+
messageTemplate: "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}",
|
|
52
|
+
model: "openai/gpt-5.2-mini",
|
|
53
|
+
deliver: true,
|
|
54
|
+
channel: "last",
|
|
55
|
+
// to: "+15551234567"
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
If you want a fixed channel, set `channel` + `to`. Otherwise `channel: "last"`
|
|
63
|
+
uses the last delivery route (falls back to WhatsApp).
|
|
64
|
+
|
|
65
|
+
To force a cheaper model for Gmail runs, set `model` in the mapping
|
|
66
|
+
(`provider/model` or alias). If you enforce `agents.defaults.models`, include it there.
|
|
67
|
+
|
|
68
|
+
To set a default model and thinking level specifically for Gmail hooks, add
|
|
69
|
+
`hooks.gmail.model` / `hooks.gmail.thinking` in your config:
|
|
70
|
+
|
|
71
|
+
```json5
|
|
72
|
+
{
|
|
73
|
+
hooks: {
|
|
74
|
+
gmail: {
|
|
75
|
+
model: "openrouter/meta-llama/llama-3.3-70b-instruct:free",
|
|
76
|
+
thinking: "off",
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Notes:
|
|
83
|
+
|
|
84
|
+
- Per-hook `model`/`thinking` in the mapping still overrides these defaults.
|
|
85
|
+
- Fallback order: `hooks.gmail.model` → `agents.defaults.model.fallbacks` → primary (auth/rate-limit/timeouts).
|
|
86
|
+
- If `agents.defaults.models` is set, the Gmail model must be in the allowlist.
|
|
87
|
+
- Gmail hook content is wrapped with external-content safety boundaries by default.
|
|
88
|
+
To disable (dangerous), set `hooks.gmail.allowUnsafeExternalContent: true`.
|
|
89
|
+
|
|
90
|
+
To customize payload handling further, add `hooks.mappings` or a JS/TS transform module
|
|
91
|
+
under `hooks.transformsDir` (see [Webhooks](/automation/webhook)).
|
|
92
|
+
|
|
93
|
+
## Wizard (recommended)
|
|
94
|
+
|
|
95
|
+
Use the Milaidy helper to wire everything together (installs deps on macOS via brew):
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
milaidy webhooks gmail setup \
|
|
99
|
+
--account milaidy@gmail.com
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Defaults:
|
|
103
|
+
|
|
104
|
+
- Uses Tailscale Funnel for the public push endpoint.
|
|
105
|
+
- Writes `hooks.gmail` config for `milaidy webhooks gmail run`.
|
|
106
|
+
- Enables the Gmail hook preset (`hooks.presets: ["gmail"]`).
|
|
107
|
+
|
|
108
|
+
Path note: when `tailscale.mode` is enabled, Milaidy automatically sets
|
|
109
|
+
`hooks.gmail.serve.path` to `/` and keeps the public path at
|
|
110
|
+
`hooks.gmail.tailscale.path` (default `/gmail-pubsub`) because Tailscale
|
|
111
|
+
strips the set-path prefix before proxying.
|
|
112
|
+
If you need the backend to receive the prefixed path, set
|
|
113
|
+
`hooks.gmail.tailscale.target` (or `--tailscale-target`) to a full URL like
|
|
114
|
+
`http://127.0.0.1:8788/gmail-pubsub` and match `hooks.gmail.serve.path`.
|
|
115
|
+
|
|
116
|
+
Want a custom endpoint? Use `--push-endpoint <url>` or `--tailscale off`.
|
|
117
|
+
|
|
118
|
+
Platform note: on macOS the wizard installs `gcloud`, `gogcli`, and `tailscale`
|
|
119
|
+
via Homebrew; on Linux install them manually first.
|
|
120
|
+
|
|
121
|
+
Gateway auto-start (recommended):
|
|
122
|
+
|
|
123
|
+
- When `hooks.enabled=true` and `hooks.gmail.account` is set, the Gateway starts
|
|
124
|
+
`gog gmail watch serve` on boot and auto-renews the watch.
|
|
125
|
+
- Set `MILAIDY_SKIP_GMAIL_WATCHER=1` to opt out (useful if you run the daemon yourself).
|
|
126
|
+
- Do not run the manual daemon at the same time, or you will hit
|
|
127
|
+
`listen tcp 127.0.0.1:8788: bind: address already in use`.
|
|
128
|
+
|
|
129
|
+
Manual daemon (starts `gog gmail watch serve` + auto-renew):
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
milaidy webhooks gmail run
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## One-time setup
|
|
136
|
+
|
|
137
|
+
1. Select the GCP project **that owns the OAuth client** used by `gog`.
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
gcloud auth login
|
|
141
|
+
gcloud config set project <project-id>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Note: Gmail watch requires the Pub/Sub topic to live in the same project as the OAuth client.
|
|
145
|
+
|
|
146
|
+
2. Enable APIs:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
gcloud services enable gmail.googleapis.com pubsub.googleapis.com
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
3. Create a topic:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
gcloud pubsub topics create gog-gmail-watch
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
4. Allow Gmail push to publish:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
gcloud pubsub topics add-iam-policy-binding gog-gmail-watch \
|
|
162
|
+
--member=serviceAccount:gmail-api-push@system.gserviceaccount.com \
|
|
163
|
+
--role=roles/pubsub.publisher
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Start the watch
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
gog gmail watch start \
|
|
170
|
+
--account milaidy@gmail.com \
|
|
171
|
+
--label INBOX \
|
|
172
|
+
--topic projects/<project-id>/topics/gog-gmail-watch
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Save the `history_id` from the output (for debugging).
|
|
176
|
+
|
|
177
|
+
## Run the push handler
|
|
178
|
+
|
|
179
|
+
Local example (shared token auth):
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
gog gmail watch serve \
|
|
183
|
+
--account milaidy@gmail.com \
|
|
184
|
+
--bind 127.0.0.1 \
|
|
185
|
+
--port 8788 \
|
|
186
|
+
--path /gmail-pubsub \
|
|
187
|
+
--token <shared> \
|
|
188
|
+
--hook-url http://127.0.0.1:18789/hooks/gmail \
|
|
189
|
+
--hook-token MILAIDY_HOOK_TOKEN \
|
|
190
|
+
--include-body \
|
|
191
|
+
--max-bytes 20000
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Notes:
|
|
195
|
+
|
|
196
|
+
- `--token` protects the push endpoint (`x-gog-token` or `?token=`).
|
|
197
|
+
- `--hook-url` points to Milaidy `/hooks/gmail` (mapped; isolated run + summary to main).
|
|
198
|
+
- `--include-body` and `--max-bytes` control the body snippet sent to Milaidy.
|
|
199
|
+
|
|
200
|
+
Recommended: `milaidy webhooks gmail run` wraps the same flow and auto-renews the watch.
|
|
201
|
+
|
|
202
|
+
## Expose the handler (advanced, unsupported)
|
|
203
|
+
|
|
204
|
+
If you need a non-Tailscale tunnel, wire it manually and use the public URL in the push
|
|
205
|
+
subscription (unsupported, no guardrails):
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
cloudflared tunnel --url http://127.0.0.1:8788 --no-autoupdate
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Use the generated URL as the push endpoint:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
gcloud pubsub subscriptions create gog-gmail-watch-push \
|
|
215
|
+
--topic gog-gmail-watch \
|
|
216
|
+
--push-endpoint "https://<public-url>/gmail-pubsub?token=<shared>"
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Production: use a stable HTTPS endpoint and configure Pub/Sub OIDC JWT, then run:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
gog gmail watch serve --verify-oidc --oidc-email <svc@...>
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Test
|
|
226
|
+
|
|
227
|
+
Send a message to the watched inbox:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
gog gmail send \
|
|
231
|
+
--account milaidy@gmail.com \
|
|
232
|
+
--to milaidy@gmail.com \
|
|
233
|
+
--subject "watch test" \
|
|
234
|
+
--body "ping"
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Check watch state and history:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
gog gmail watch status --account milaidy@gmail.com
|
|
241
|
+
gog gmail history --account milaidy@gmail.com --since <historyId>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Troubleshooting
|
|
245
|
+
|
|
246
|
+
- `Invalid topicName`: project mismatch (topic not in the OAuth client project).
|
|
247
|
+
- `User not authorized`: missing `roles/pubsub.publisher` on the topic.
|
|
248
|
+
- Empty messages: Gmail push only provides `historyId`; fetch via `gog gmail history`.
|
|
249
|
+
|
|
250
|
+
## Cleanup
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
gog gmail watch stop --account milaidy@gmail.com
|
|
254
|
+
gcloud pubsub subscriptions delete gog-gmail-watch-push
|
|
255
|
+
gcloud pubsub topics delete gog-gmail-watch
|
|
256
|
+
```
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Poll sending via gateway + CLI"
|
|
3
|
+
read_when:
|
|
4
|
+
- Adding or modifying poll support
|
|
5
|
+
- Debugging poll sends from the CLI or gateway
|
|
6
|
+
title: "Polls"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Polls
|
|
10
|
+
|
|
11
|
+
## Supported channels
|
|
12
|
+
|
|
13
|
+
- WhatsApp (web channel)
|
|
14
|
+
- Discord
|
|
15
|
+
- MS Teams (Adaptive Cards)
|
|
16
|
+
|
|
17
|
+
## CLI
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# WhatsApp
|
|
21
|
+
milaidy message poll --target +15555550123 \
|
|
22
|
+
--poll-question "Lunch today?" --poll-option "Yes" --poll-option "No" --poll-option "Maybe"
|
|
23
|
+
milaidy message poll --target 123456789@g.us \
|
|
24
|
+
--poll-question "Meeting time?" --poll-option "10am" --poll-option "2pm" --poll-option "4pm" --poll-multi
|
|
25
|
+
|
|
26
|
+
# Discord
|
|
27
|
+
milaidy message poll --channel discord --target channel:123456789 \
|
|
28
|
+
--poll-question "Snack?" --poll-option "Pizza" --poll-option "Sushi"
|
|
29
|
+
milaidy message poll --channel discord --target channel:123456789 \
|
|
30
|
+
--poll-question "Plan?" --poll-option "A" --poll-option "B" --poll-duration-hours 48
|
|
31
|
+
|
|
32
|
+
# MS Teams
|
|
33
|
+
milaidy message poll --channel msteams --target conversation:19:abc@thread.tacv2 \
|
|
34
|
+
--poll-question "Lunch?" --poll-option "Pizza" --poll-option "Sushi"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Options:
|
|
38
|
+
|
|
39
|
+
- `--channel`: `whatsapp` (default), `discord`, or `msteams`
|
|
40
|
+
- `--poll-multi`: allow selecting multiple options
|
|
41
|
+
- `--poll-duration-hours`: Discord-only (defaults to 24 when omitted)
|
|
42
|
+
|
|
43
|
+
## Gateway RPC
|
|
44
|
+
|
|
45
|
+
Method: `poll`
|
|
46
|
+
|
|
47
|
+
Params:
|
|
48
|
+
|
|
49
|
+
- `to` (string, required)
|
|
50
|
+
- `question` (string, required)
|
|
51
|
+
- `options` (string[], required)
|
|
52
|
+
- `maxSelections` (number, optional)
|
|
53
|
+
- `durationHours` (number, optional)
|
|
54
|
+
- `channel` (string, optional, default: `whatsapp`)
|
|
55
|
+
- `idempotencyKey` (string, required)
|
|
56
|
+
|
|
57
|
+
## Channel differences
|
|
58
|
+
|
|
59
|
+
- WhatsApp: 2-12 options, `maxSelections` must be within option count, ignores `durationHours`.
|
|
60
|
+
- Discord: 2-10 options, `durationHours` clamped to 1-768 hours (default 24). `maxSelections > 1` enables multi-select; Discord does not support a strict selection count.
|
|
61
|
+
- MS Teams: Adaptive Card polls (Milaidy-managed). No native poll API; `durationHours` is ignored.
|
|
62
|
+
|
|
63
|
+
## Agent tool (Message)
|
|
64
|
+
|
|
65
|
+
Use the `message` tool with `poll` action (`to`, `pollQuestion`, `pollOption`, optional `pollMulti`, `pollDurationHours`, `channel`).
|
|
66
|
+
|
|
67
|
+
Note: Discord has no “pick exactly N” mode; `pollMulti` maps to multi-select.
|
|
68
|
+
Teams polls are rendered as Adaptive Cards and require the gateway to stay online
|
|
69
|
+
to record votes in `~/.milaidy/msteams-polls.json`.
|