samograph 0.6.0 → 0.7.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/README.md +21 -5
- package/dist/cli.js +746 -294
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,7 +31,8 @@ samograph gives an AI agent a small set of meeting tools:
|
|
|
31
31
|
- `join` - bring a Recall.ai bot into a Zoom or Google Meet call.
|
|
32
32
|
- `watch` - stream live transcript lines to the agent.
|
|
33
33
|
- `notes` - maintain a structured Google Doc agenda with important points, decisions, and action items.
|
|
34
|
-
- `chat` - send a deliberate message into the meeting chat.
|
|
34
|
+
- `chat` - send a deliberate message into the meeting chat (plays a soft chime into the call audio so people notice it).
|
|
35
|
+
- `intro` - post a short self-introduction into the meeting chat (also available as `join --intro`).
|
|
35
36
|
- `presence` - update the bot camera state shown in the meeting.
|
|
36
37
|
- `frame` - export the current call view on demand.
|
|
37
38
|
- `leave` - remove the bot and clean up local state.
|
|
@@ -58,12 +59,20 @@ samograph watch/notes/chat/frame
|
|
|
58
59
|
|
|
59
60
|
## Integration
|
|
60
61
|
|
|
61
|
-
`join` starts a local callback server and exposes it with `ngrok http` so Recall.ai can deliver HTTPS/WSS events back to your machine. The free ngrok HTTP plan is enough for webhooks and transcription, but its browser interstitial blocks the presence camera page — `join` then warns and joins without the camera (see Dynamic Bot Presence).
|
|
62
|
+
`join` starts a local callback server and exposes it with `ngrok http` so Recall.ai can deliver HTTPS/WSS events back to your machine. The free ngrok HTTP plan is enough for webhooks and transcription, but its browser interstitial blocks the presence camera page — `join` then warns and joins without the camera (see Dynamic Bot Presence). Alternatives: `--tunnel cloudflared` starts a free cloudflared quick tunnel instead of ngrok, or pass `--webhook-base <URL>` to use an existing external tunnel (localtunnel, cloudflared, etc.) and skip spawning one entirely; localtunnel has the same interstitial limitation.
|
|
62
63
|
|
|
63
64
|
ngrok TCP is only needed for the optional RTMP path (`--rtmp`) and requires a credit/debit card on file at ngrok.com (free plan — the card is not charged). The standard WebSocket frame path does not need TCP or card verification.
|
|
64
65
|
|
|
65
66
|
Webhook, frame, and presence routes are token-protected, and default runtime files stay under `~/.samograph/`.
|
|
66
67
|
|
|
68
|
+
## Tunnel Health
|
|
69
|
+
|
|
70
|
+
A tunnel that stops relaying requests is worse than no tunnel: the bot would sit in the meeting while the transcript silently stays empty (this is exactly what an ngrok free-account request-limit error, `ERR_NGROK_727`, looks like mid-call). samograph treats webhook reachability as core:
|
|
71
|
+
|
|
72
|
+
- **join refuses when the tunnel is dead.** After the public URL is known, `join` fetches `<public-url>/health` with a one-time nonce and requires its own server's answer back. On failure it exits with the ngrok error code when one is reported (e.g. `ERR_NGROK_727: account HTTP request limit exceeded`) instead of joining a call it cannot hear. The presence camera preflight still merely degrades — the camera is optional, webhooks are not.
|
|
73
|
+
- **a mid-call watchdog warns in the transcript stream.** The callback server re-checks the tunnel every 60 s. After 2 consecutive failures it appends a line like `[2026-06-11 17:03:05] SAMOGRAPH-WARNING: tunnel unreachable (ERR_NGROK_727) - transcript may be incomplete; rejoin with --tunnel cloudflared or --webhook-base` to the live transcript — so an agent following `samograph watch` sees it immediately — and mirrors it to stderr. It warns once per outage and writes a single `SAMOGRAPH-WARNING: tunnel recovered` line when the tunnel comes back.
|
|
74
|
+
- **quota math.** The presence camera page is loaded by Recall through the tunnel, so its same-origin `/presence.json` polls also count against tunnel request quotas: at the old fixed 1 s poll that alone was ~3600 requests/hour. The page now polls at 1 s only while the presence snapshot is changing and backs off to 5 s after 30 s of no changes; the watchdog adds ~60/hour. If you are on a free ngrok account, prefer `--tunnel cloudflared` (no request limits) for long or camera-heavy calls.
|
|
75
|
+
|
|
67
76
|
## Agent Workflow
|
|
68
77
|
|
|
69
78
|
```bash
|
|
@@ -91,7 +100,7 @@ Use `chat` only when you intentionally want to write into the meeting chat. Othe
|
|
|
91
100
|
|
|
92
101
|
## Dynamic Bot Presence
|
|
93
102
|
|
|
94
|
-
`join` gives the Recall bot a token-protected local camera page through the same public tunnel used for webhooks. The page URL carries a read-only token (valid only for viewing the page; `/presence.json` requires the same token in the `X-Samograph-Presence-Token` header, which the page sends when polling); presence updates require a separate write token that `join` keeps in local state and `samograph presence` sends in a header. The page starts as `listening` and refreshes itself from the
|
|
103
|
+
`join` gives the Recall bot a token-protected local camera page through the same public tunnel used for webhooks. The page URL carries a read-only token (valid only for viewing the page; `/presence.json` requires the same token in the `X-Samograph-Presence-Token` header, which the page sends when polling); presence updates require a separate write token that `join` keeps in local state and `samograph presence` sends in a header. The page starts as `listening` and refreshes itself from the callback server every second while the presence snapshot is changing, backing off to every 5 seconds after 30 seconds without changes (the polls travel through the public tunnel, so this preserves tunnel request quota — see Tunnel Health). Pick the background mode with `join --presence-bg <sphere|field|static|cycle>` (`sphere` is the default; `static` is the cheapest to render; `cycle` alternates between field and sphere; unknown values fall back to `sphere`). The mode is fixed at join time.
|
|
95
104
|
|
|
96
105
|
The presence camera requires the tunnel to serve the page cleanly to a browser. Free-ngrok and localtunnel show an interstitial page to browser user agents, which blocks the camera: `join` detects this in a preflight check, prints a warning, and joins **without** the presence camera — transcription, chat, and frames are unaffected, but `samograph presence` is unavailable for that call. Use a paid/clean tunnel (e.g. a paid ngrok plan or cloudflared) for the presence camera, or pass `join --no-presence` to skip the camera and the preflight entirely.
|
|
97
106
|
|
|
@@ -162,7 +171,8 @@ Archive filenames include call id, UTC timestamp, source type, and participant i
|
|
|
162
171
|
## Important Flags
|
|
163
172
|
|
|
164
173
|
- `join --no-ws-video` - disable the default WebSocket frame path (e.g. when using RTMP instead).
|
|
165
|
-
- `join --
|
|
174
|
+
- `join --tunnel cloudflared` - start a free cloudflared quick tunnel instead of ngrok (binary from `PATH` or `CLOUDFLARED_BIN`). Recommended when ngrok hits its free-tier request limit (`ERR_NGROK_727`); see Tunnel Health. Default: `--tunnel ngrok`.
|
|
175
|
+
- `join --webhook-base URL` - use an existing public tunnel (localtunnel, cloudflared quick tunnel, etc.) pointing at `--port` instead of starting one. Mutually exclusive with `--tunnel`. E.g. run `npx localtunnel --port 8080`, then pass the printed `https://*.loca.lt` URL here. The join-time health round-trip still verifies it relays requests.
|
|
166
176
|
- `join --variant web_4_core` - ask Recall to run the output-media webpage on a larger bot instance. Use this when the camera webpage reports low render FPS or looks choppy. `web` is the default Recall instance; `web_gpu` is available for WebGL-heavy pages.
|
|
167
177
|
- `join --no-presence` - join without the presence camera page and skip the camera preflight (e.g. when the tunnel serves an interstitial).
|
|
168
178
|
- `join --presence-bg MODE` - presence camera background: `sphere` (default), `field`, `static` (cheapest), or `cycle` (alternates field/sphere); fixed at join time.
|
|
@@ -188,7 +198,8 @@ Archive filenames include call id, UTC timestamp, source type, and participant i
|
|
|
188
198
|
- `notes decision <text>` - add a decision.
|
|
189
199
|
- `notes action <text>` - add an action item.
|
|
190
200
|
- `notes transcript [--from-start]` - explicitly mirror raw transcript lines.
|
|
191
|
-
- `chat <message>` - send meeting chat.
|
|
201
|
+
- `chat <message>` - send meeting chat. After a successful send it best-effort plays a short, soft chime **into the call's audio** via Recall's `output_audio` endpoint, so participants actually hear that the bot posted; chat still succeeds if audio output fails. It also pings the local presence server so the bot camera animates the same cue (camera-page WebAudio is video-only and inaudible in Recall's headless renderer, so the call-audio path is what people hear).
|
|
202
|
+
- `intro [--intro-text TEXT] [--context] [--bot-id ID]` - post a short self-introduction (who the bot is and what it can do) into the meeting chat on demand. Reuses `chat` (same bot-id resolution, error handling, and chime). Default text is English and concise; override it with `--intro-text` (e.g. a localized or freshly generated intro the agent composes). `--context` appends the first spoken line the bot has heard so far ("The first thing I heard was — …"), skipped when the transcript is still empty. See also `join --intro`, which posts the default intro automatically once the bot is admitted (English, since no transcript exists yet to detect the call's language).
|
|
192
203
|
- `presence <listening|thinking|speaking|acting|idle> [message]` - update the bot camera state; explicit messages are shown as live Comments activity on the camera page, bare state toggles only switch the state with its default message, and transcript webhooks add recent "heard" lines automatically without changing the agent-set state.
|
|
193
204
|
- `frames` - list buffered WebSocket frame sources and metadata.
|
|
194
205
|
- `frame [--source SOURCE] [--out FILE] [--archive]` - write an in-memory frame to disk on demand.
|
|
@@ -216,6 +227,11 @@ Generated runtime files are ignored by git. Do not point `--frame-dir` or `--out
|
|
|
216
227
|
- `SAMOGRAPH_FRAME_TOKEN` - token required by the frame routes and `/video-ws`.
|
|
217
228
|
- `SAMOGRAPH_PRESENCE_TOKEN` - read token for the presence page and `/presence.json`.
|
|
218
229
|
- `SAMOGRAPH_PRESENCE_WRITE_TOKEN` - write token required by `POST /presence`.
|
|
230
|
+
- `SAMOGRAPH_PUBLIC_BASE` - public tunnel base URL for the mid-call tunnel watchdog (`join` passes it as `--public-base`; the env var is the fallback for manual `_serve` runs; empty disables the watchdog).
|
|
231
|
+
|
|
232
|
+
Tunnel binaries:
|
|
233
|
+
|
|
234
|
+
- `CLOUDFLARED_BIN` - path to the cloudflared binary used by `join --tunnel cloudflared` (default: `cloudflared` from `PATH`).
|
|
219
235
|
|
|
220
236
|
Path overrides, mainly for tests and packaging:
|
|
221
237
|
|