Commit Graph

1709 Commits (9632ebed7b81b7ea258b1aa0542c8b0ad8d016fd)

Author SHA1 Message Date
Randy Torres ff79db0a99 fix(auth): use anthropic oauth email profile
Use Anthropic OAuth profile email as the profile identifier when available. This fixes cases where Anthropic returns an email-based profile id rather than an explicit id field.
2026-01-07 06:31:02 +00:00
Peter Steinberger 8b1263ce11 fix: split status activation line 2026-01-07 07:26:52 +01:00
Peter Steinberger dc941b7e57 fix: refresh status output 2026-01-07 07:22:06 +01:00
Matthew Dicembrino 4f10279ac3 fix: delete legacy auth.json after migration to prevent stale token overwrites (#363) 2026-01-07 01:15:38 -05:00
Peter Steinberger 50dec39d13 fix: honor sandboxed built-in tools 2026-01-07 06:12:56 +00:00
Peter Steinberger 03928106c7 fix: order reasoning before reply text 2026-01-07 07:05:07 +01:00
Peter Steinberger 75c66acfd8 feat: update subagent announce + archive 2026-01-07 06:53:01 +01:00
Peter Steinberger 1673a221f8 feat: add /reasoning reasoning visibility 2026-01-07 06:17:31 +01:00
Peter Steinberger cb2a72f8a9 test(routing): add route-reply coverage 2026-01-07 05:07:53 +00:00
Peter Steinberger 3668388912 fix(routing): harden originating reply routing 2026-01-07 05:02:34 +00:00
Josh Lehman 5414da9fd4 fix(routing): handle cross-provider messages in collect mode
When queued messages come from different providers (Slack + Telegram),
process them individually instead of collecting into a single prompt.
This ensures each reply routes back to its originating provider.

- Add hasCrossProviderItems() to detect multi-provider queues
- Skip collect mode when cross-provider detected
- Preserve originatingChannel/originatingTo when collecting same-provider
2026-01-07 04:51:33 +00:00
Josh Lehman 2d67ec5bfa fix(routing): only route to originating channel when cross-provider
When OriginatingChannel matches Surface (same provider), use normal
dispatcher. Only route via routeReply() when they differ, ensuring
cross-provider messages (e.g., Telegram queued while Slack active)
get routed back to their origin.
2026-01-07 04:51:33 +00:00
Josh Lehman 9d50ebad7d feat(routing): route replies to originating channel
Implement reply routing based on OriginatingChannel/OriginatingTo fields.
This ensures replies go back to the provider where the message originated
instead of using the session's lastChannel.

Changes:
- Add OriginatingChannel/OriginatingTo fields to MsgContext (templating.ts)
- Add originatingChannel/originatingTo fields to FollowupRun (queue.ts)
- Create route-reply.ts with provider-agnostic router
- Update all providers (Telegram, Slack, Discord, Signal, iMessage)
  to pass originating channel info
- Update reply.ts to pass originating channel to followupRun
- Update followup-runner.ts to use route-reply for originating channels

This addresses the issue where messages from one provider (e.g., Slack)
would receive replies on a different provider (e.g., Telegram) because
the queue used the last active dispatcher instead of the originating one.
2026-01-07 04:51:33 +00:00
Peter Steinberger 514fcfe77e fix: harden sub-agent model overrides 2026-01-07 04:48:37 +00:00
Peter Steinberger 12d57da53a fix: normalize provider aliases in auth order 2026-01-07 05:43:32 +01:00
mneves75 8187baab18 test: format models list alias coverage 2026-01-07 05:31:01 +01:00
mneves75 3550dc294d fix: normalize z.ai provider ids in auth profiles 2026-01-07 05:31:01 +01:00
mneves75 8954f7719c Test: cover z.ai normalization 2026-01-07 05:30:06 +01:00
mneves75 0ddfbf5534 Feat: normalize z.ai provider ids 2026-01-07 05:30:06 +01:00
Peter Steinberger 42ae2341aa fix: harden pairing flow 2026-01-07 05:06:04 +01:00
Peter Steinberger 6ffece68b0 fix(doctor): add headless flags + auto-migrate sessions 2026-01-07 04:43:24 +01:00
Peter Steinberger 9c9ae5aa54 fix(imessage): harden abort shutdown 2026-01-07 03:41:23 +00:00
Anton Sotkov 08fc0b3809 fix: imsg unhandled promises 2026-01-07 03:41:23 +00:00
Peter Steinberger 8ef0609f8e refactor: share reaction schemas and notes 2026-01-07 04:24:11 +01:00
Peter Steinberger 073b16a3a0 fix: clean up reaction tooling 2026-01-07 04:16:39 +01:00
Peter Steinberger 3afef2d504 feat: unify provider reaction tools 2026-01-07 04:16:39 +01:00
Sash Zats 551a8d5683 Add WhatsApp reactions support
Summary:

Test Plan:
2026-01-07 04:16:39 +01:00
Peter Steinberger aa87d6cee8 refactor(relay): add --smoke entrypoint 2026-01-07 03:12:30 +00:00
Peter Steinberger 59cc15f3cc fix(relay): guard QR smoke mode 2026-01-07 02:42:55 +00:00
Peter Steinberger ff102e2afa Merge PR #358 2026-01-07 02:42:53 +00:00
Peter Steinberger aa635af6d0 refactor: unify outbound result envelopes 2026-01-07 02:36:05 +00:00
DB Hurley 9d820a628f fix(relay): implement CLAWDBOT_SMOKE_QR handler for packaging 2026-01-06 21:32:04 -05:00
Peter Steinberger 4bf5f37a44 refactor: streamline outbound payload handling 2026-01-07 02:30:42 +00:00
Peter Steinberger 3fedd0d1d5 fix(outbound): guard optional delivery fields 2026-01-07 02:19:42 +00:00
Peter Steinberger 59502552ae fix(telegram): import native reply helper 2026-01-07 02:19:42 +00:00
Peter Steinberger d7bc5b58fc refactor(telegram): polish topic threading 2026-01-07 02:19:42 +00:00
Peter Steinberger 80112433a5 fix(telegram): support forum topics
Co-authored-by: Daniel Griesser <HazAT@users.noreply.github.com>
Co-authored-by: Nacho Iacovino <nachoiacovino@users.noreply.github.com>
Co-authored-by: Randy Ventures <RandyVentures@users.noreply.github.com>
2026-01-07 02:19:42 +00:00
Peter Steinberger 023a124312 test: cover gmail tailscale error formatting 2026-01-07 03:16:52 +01:00
Peter Steinberger 2986447935 fix: improve gmail tailscale errors 2026-01-07 03:10:35 +01:00
Peter Steinberger 467d4e17fe feat: add sandbox scope default 2026-01-07 02:52:41 +01:00
Peter Steinberger 15b7560a9b refactor: reuse gateway output helpers 2026-01-07 01:43:02 +00:00
Peter Steinberger b88c4e9d20 chore: clean up lint and scratchpad 2026-01-07 01:28:46 +00:00
Peter Steinberger bc9a3ce32a refactor: unify outbound delivery formatting 2026-01-07 01:26:09 +00:00
Peter Steinberger 3fbe2963b3 test: align outbound normalization 2026-01-07 01:22:55 +00:00
Peter Steinberger 8ba6473462 style: fix send json indent 2026-01-07 01:21:29 +00:00
Peter Steinberger dd78c26e6d style: format direct send json 2026-01-07 01:21:03 +00:00
Peter Steinberger 2ce5df3efc style: align outbound delivery formatting 2026-01-07 01:20:40 +00:00
Peter Steinberger aefaed159b refactor: normalize outbound payload delivery 2026-01-07 01:19:47 +00:00
Peter Steinberger f171d509bb refactor: centralize outbound target validation 2026-01-07 01:16:39 +00:00
Sash Zats f1643a5b8d Heartbeat: resolve main session key for session store 2026-01-06 20:14:30 -05:00
Peter Steinberger f5938f8114 refactor: unify outbound delivery 2026-01-07 01:13:04 +00:00
Peter Steinberger 1ae5e9a26b feat: add docs search command 2026-01-07 02:03:06 +01:00
Sash Zats eb8d7a19af Cron: enqueue system events in main session 2026-01-06 19:55:03 -05:00
Erik cd4e2023ab fix(agent): capture compaction retry AbortError for model fallback
Wrap waitForCompactionRetry() in try/catch to capture AbortError
that was escaping and bypassing the model fallback mechanism.

When a timeout fires, session.abort() causes both session.prompt()
and waitForCompactionRetry() to throw AbortError. Previously only
the prompt error was captured, allowing the compaction error to
escape to model-fallback.ts where it was immediately re-thrown
(line 199: isAbortError check), bypassing fallback model attempts.

Fixes #313
2026-01-07 01:44:37 +01:00
Peter Steinberger 0116184b1c docs: recommend WSL2 for Windows installs 2026-01-07 01:21:36 +01:00
Peter Steinberger 62112d9978 feat: add onboarding doc links 2026-01-07 01:19:31 +01:00
Peter Steinberger 19c95d0ff7 fix(auth): serialize profile stats updates 2026-01-07 01:06:51 +01:00
Peter Steinberger 96d72ff91e fix(auth): lock auth profile updates 2026-01-07 01:00:47 +01:00
Muhammed Mukhthar CM eb5f758f6b fix(auth): improve multi-account round-robin rotation and 429 handling
This commit fixes several issues with multi-account OAuth rotation that
were causing slow responses and inefficient account cycling.

## Changes

### 1. Fix usageStats race condition (auth-profiles.ts)

The `markAuthProfileUsed`, `markAuthProfileCooldown`, `markAuthProfileGood`,
and `clearAuthProfileCooldown` functions were using a stale in-memory store
passed as a parameter. Long-running sessions would overwrite usageStats
updates from concurrent sessions when saving.

**Fix:** Re-read the store from disk before each update to get fresh
usageStats from other sessions, then merge the update.

### 2. Capture AbortError from waitForCompactionRetry (pi-embedded-runner.ts)

When a request timed out, `session.abort()` was called which throws an
`AbortError`. The code structure was:

```javascript
try {
  await session.prompt(params.prompt);
} catch (err) {
  promptError = err;  // Catches AbortError here
}
await waitForCompactionRetry();  // But THIS also throws AbortError!
```

The second `AbortError` from `waitForCompactionRetry()` escaped and
bypassed the rotation/fallback logic entirely.

**Fix:** Wrap `waitForCompactionRetry()` in its own try/catch to capture
the error as `promptError`, enabling proper timeout handling.

Root cause analysis and fix proposed by @erikpr1994 in #313.

Fixes #313

### 3. Fail fast on 429 rate limits (pi-ai patch)

The pi-ai library was retrying 429 errors up to 3 times with exponential
backoff before throwing. This meant a rate-limited account would waste
30+ seconds retrying before our rotation code could try the next account.

**Fix:** Patch google-gemini-cli.js to:
- Throw immediately on first 429 (no retries)
- Not catch and retry 429 errors in the network error handler

This allows the caller to rotate to the next account instantly on rate limit.

Note: We submitted this fix upstream (https://github.com/badlogic/pi-mono/pull/504)
but it was closed without merging. Keeping as a local patch for now.

## Testing

With 6 Antigravity accounts configured:
- Accounts rotate properly based on lastUsed (round-robin)
- 429s trigger immediate rotation to next account
- usageStats persist correctly across concurrent sessions
- Cooldown tracking works as expected

## Before/After

**Before:** Multiple 429 retries on same account, 30-90s delays
**After:** Instant rotation on 429, responses in seconds
2026-01-07 00:56:32 +01:00
VAC ff200e3993 fix(discord): handle voice messages with empty content
Discord voice messages have empty `content` with the audio in attachments.
The nullish coalescing operator (`??`) doesn't fall through on empty strings,
so voice messages were being dropped as 'empty content'.

Changed to logical OR (`||`) so empty string falls through to media placeholder.
2026-01-06 23:35:30 +00:00
Peter Steinberger 7214cf39ec fix: prefer home linuxbrew paths 2026-01-07 00:18:07 +01:00
Peter Steinberger b57d36f49c fix(sessions_spawn): hard-fail invalid model overrides 2026-01-06 23:17:35 +00:00
Azade 0429a4b63b test(sessions_spawn): add test for model parameter 2026-01-06 23:17:35 +00:00
Azade 274f408e6f feat(sessions_spawn): add model parameter for sub-agent model override 2026-01-06 23:17:35 +00:00
Peter Steinberger 02c9cf0ff4 chore: remove duplicate daemon runtime imports 2026-01-07 00:14:08 +01:00
Peter Steinberger dd0d23cd96 test(commands): add /stop native regression 2026-01-06 23:11:57 +00:00
Peter Steinberger e0efcda77f fix(commands): wire /stop across chat commands 2026-01-06 23:11:57 +00:00
Nacho Iacovino 0df7c3addf feat(telegram): add /stop command to abort running agent
Adds a /stop command that:
- Can interrupt a running agent session mid-execution
- Works in both DMs and group chats (including forum topics)
- Uses grammy's bot.command() to run before the main message handler
- Returns status: stopped, stop requested, or nothing running

Also fixes session key lookup in pi-embedded-runner to use sessionKey
instead of sessionId, ensuring /stop finds the correct active run.
2026-01-06 23:11:57 +00:00
Peter Steinberger 5bc3f13b46 feat: colorize models auth key labels 2026-01-07 00:10:01 +01:00
Peter Steinberger b357746e1c feat: add richer color to models output 2026-01-07 00:07:50 +01:00
Peter Steinberger 79f813e18e style: format lint offenders 2026-01-07 00:04:44 +01:00
Peter Steinberger 0ad74ee941 test: mock select prompt in doctor tests 2026-01-07 00:01:50 +01:00
Peter Steinberger 55278c1c71 feat: add daemon runtime prompts 2026-01-06 23:51:00 +01:00
Peter Steinberger c920ee1166 Merge branch 'pr-335-merge' 2026-01-06 23:45:35 +01:00
Peter Steinberger 5939363eed fix: include telegram group sender in envelope headers 2026-01-06 22:34:02 +00:00
Peter Steinberger 8d50d08936 style: format daemon runtime changes 2026-01-06 23:29:38 +01:00
Peter Steinberger 8911a79d7f docs: rewrite cron jobs guide and heartbeat notes 2026-01-06 22:28:42 +00:00
Peter Steinberger 707f7918bc feat: add gateway daemon runtime selector 2026-01-06 23:27:58 +01:00
Peter Steinberger 18c43fe462 fix: bootstrap linuxbrew for skills 2026-01-06 23:27:38 +01:00
Peter Steinberger 39d2ba78b7 fix(cli): harden pairing provider parse 2026-01-06 22:17:18 +00:00
Peter Steinberger 0931a65ab2
fix: auto-recover from Gemini session corruption
Auto-merge after checks.
2026-01-06 22:12:05 +00:00
Peter Steinberger fec7f37271 merge upstream/main 2026-01-06 23:09:01 +01:00
Peter Steinberger 86b56b2308 fix: harden gemini session reset 2026-01-06 23:06:01 +01:00
Peter Steinberger 2771001720 fix(state): auto-migrate legacy agent dir 2026-01-06 22:04:23 +00:00
Peter Steinberger 7aa7fa79d0 feat: update heartbeat defaults 2026-01-06 21:54:42 +00:00
Peter Steinberger dba09058f5 fix(agents): default agent dir to multi-agent path 2026-01-06 21:54:42 +00:00
Peter Steinberger 96164b5955 fix: improve socket error handling 2026-01-06 22:43:29 +01:00
Emanuel Stadler fb17a32283 feat: enhance error handling for socket connection errors
- Added `isError` property to `EmbeddedPiRunResult` and reply items to indicate error states.
- Updated error handling in `runReplyAgent` to provide more informative messages for specific socket connection errors.
2026-01-06 22:19:37 +01:00
James Groat 9b6e2478f5 fix(browser): add profile param to tabs routes and browser-tool
- tabs.ts now uses getProfileContext like other routes
- browser-tool threads profile param through all actions
- add tests for profile query param on /tabs endpoints
- update docs with browser tool profile parameter
2026-01-06 21:54:46 +01:00
James Groat 40758b16a9 fix(browser-cli): rename --profile to --browser-profile to avoid conflict with global --profile flag 2026-01-06 21:54:46 +01:00
minghinmatthewlam 2dd6b3aeb2
fix: write auth profiles to multi-agent path during onboarding
- Onboarding now writes auth profiles under ~/.clawdbot/agents/main/agent so the gateway sees credentials on first start.
- Hardened onboarding test to ignore legacy env vars.

Thanks @minghinmatthewlam!
2026-01-06 20:53:18 +00:00
Peter Steinberger 84c8209158 fix(slack): clear assistant thread status after replies 2026-01-06 21:41:30 +01:00
Shadow 8ebc789d25 Slack: send assistant thread status while typing 2026-01-06 21:34:52 +01:00
Shadow 9b22e1f6e9
feat(commands): unify chat commands (#275)
* Chat commands: registry, access groups, Carbon

* Chat commands: clear native commands on disable

* fix(commands): align command surface typing

* docs(changelog): note commands registry (PR #275)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-01-06 20:17:56 +00:00
Peter Steinberger 1bf44bf30c feat(models): show auth overview 2026-01-06 20:07:04 +00:00
Peter Steinberger 118c1e1042 fix: keep oauth profile stable 2026-01-06 19:43:28 +00:00
Peter Steinberger 67bda21811 fix: preserve markdown fences when chunking 2026-01-06 20:23:41 +01:00
Peter Steinberger 31dbc62bdd fix(telegram): prevent stuck typing after tool runs 2026-01-06 18:56:43 +00:00
Peter Steinberger 369af5fc58 style(agents): format usage helper 2026-01-06 19:54:50 +01:00
Peter Steinberger d07e78855c fix(workspace): align clawd + bootstrap 2026-01-06 19:54:50 +01:00
Abhi bdf597eb95
fix(telegram): stop typing after tool results (#322)
Thanks @AbhisekBasu1.
2026-01-06 18:54:08 +00:00
Peter Steinberger 2f24ea492b fix: restore Anthropic token accounting 2026-01-06 18:52:01 +00:00
Peter Steinberger 9fb37cbf93 style: format whatsapp inbound allowlist 2026-01-06 18:33:37 +00:00
Peter Steinberger dbfa316d19 feat: multi-agent routing + multi-account providers 2026-01-06 18:33:37 +00:00
Peter Steinberger c47aff5244 fix(onboard): clarify DM policy keys 2026-01-06 18:09:21 +01:00
Peter Steinberger 4933905366 fix(onboard): configure DM policies 2026-01-06 18:09:21 +01:00
Onur 6cf3570c5b
feat(agent): add skipBootstrap config to skip bootstrap file creation (#292) 2026-01-06 11:02:51 -06:00
Peter Steinberger b081f45b17 fix(onboard): explain DM pairing defaults 2026-01-06 17:58:06 +01:00
Muhammed Mukhthar CM 4bb53e19f9
fix(build): import tool-display.json instead of fs.readFileSync (#312) 2026-01-06 10:55:02 -06:00
Peter Steinberger 967cef80bc fix(security): lock down inbound DMs by default 2026-01-06 17:51:56 +01:00
Peter Steinberger 11b6fddcbf
Merge pull request #283 from Oncomatic/jarvis/telegram-media-error-notify
fix(telegram): notify user when media exceeds size limit
2026-01-06 15:18:52 +00:00
Peter Steinberger 3ff17b70ea chore: changelog for #293 2026-01-06 15:32:06 +01:00
Palash Oswal b91012b697
fix(cli): don't force localhost gateway url in remote mode
Fixes remote gateway setup (remote mode) by not overriding url; adds regression tests. Thanks @oswalpalash.
2026-01-06 14:30:45 +00:00
Simon Kelly 5aa1ed2c96
fix(slack): use named import for @slack/bolt App class (#299)
* fix(slack): use named import for @slack/bolt App class

The default import `import bolt from '@slack/bolt'` followed by
`const { App } = bolt` doesn't work correctly in Bun due to ESM/CJS
interop issues. The default export comes through as a function rather
than the module object.

Switching to a named import `import { App } from '@slack/bolt'`
resolves the issue and allows the Slack provider to start successfully.

* fix(slack): align Bolt mock with named App export

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-01-06 14:22:14 +00:00
VAC eadb923000 fix: auto-recover from Gemini session corruption
Detect the Gemini API error 'function call turn comes immediately after
a user turn or after a function response turn' which indicates corrupted
session history.

When detected:
- Delete the corrupted transcript file
- Remove the session entry from the store
- Return a user-friendly message asking them to retry

This prevents the error loop where every subsequent message fails with
the same error until manual intervention.

Fixes #296
2026-01-06 07:25:15 -05:00
Manuel Hettich aae5926db9 fix(telegram): notify user when media exceeds size limit
When a file exceeds mediaMaxMb, send a friendly error message
instead of silently dropping the upload.

---
🤖 Authored by Jarvis (AI assistant)
2026-01-06 08:45:07 +00:00
Peter Steinberger 3693449d7e feat: sandbox session tool visibility 2026-01-06 08:40:30 +00:00
Peter Steinberger 5926a98c52 fix(configure): don’t write auth.order by default 2026-01-06 09:25:36 +01:00
Peter Steinberger f2d353459f test(auth): stop prioritizing lastGood 2026-01-06 09:25:33 +01:00
Peter Steinberger ed2075ce69 test(gateway): deflake cron finished event wait 2026-01-06 09:25:31 +01:00
Muhammed Mukhthar CM 9e49c762e0
fix(auth): prioritize round-robin over lastGood for multi-account rotation (#281)
* fix(auth): prioritize round-robin over lastGood for multi-account rotation

When multiple OAuth accounts are configured, the round-robin rotation was
not working because lastGood was always prioritized, defeating the sort by
lastUsed.

Changes:
- Remove lastGood prioritization in resolveAuthProfileOrder
- Always apply orderProfilesByMode (sorts by lastUsed, oldest first)
- Only respect configuredOrder when explicitly set in config
- preferredProfile still takes priority for explicit user choice

Tested with 2 Google Antigravity accounts - verified alternating usage.

Follow-up to PR #269.

* style: fix formatting
2026-01-06 08:16:35 +00:00
Peter Steinberger cf1a1d107e fix: add OpenAI Codex OAuth to configure 2026-01-06 09:13:51 +01:00
Muhammed Mukhthar CM 42d1c2448e
fix(cron-tool): use generic object schema for job/patch to fix Claude via Antigravity (#280) 2026-01-06 02:13:09 -06:00
Peter Steinberger c27dd75135 build(control-ui): prefer bun for UI build 2026-01-06 09:08:25 +01:00
Peter Steinberger a279bcfeb1 feat: add sessions_spawn sub-agent tool 2026-01-06 08:41:45 +01:00
Peter Steinberger 952657d55c feat(tui): add /elev alias 2026-01-06 08:41:04 +01:00
Ayaan Zaidi 7a48b908e4
refactor: replace tsx with bun for TypeScript execution (#278) 2026-01-06 07:14:08 +00:00
Peter Steinberger dbb51006cd feat: unify group policy allowlists 2026-01-06 06:40:42 +00:00
Peter Steinberger 51e8bbd2a8 style: normalize type definitions 2026-01-06 07:21:10 +01:00
Peter Steinberger aa16b679ad fix: improve auth profile failover 2026-01-06 07:18:06 +01:00
Peter Steinberger a7b5753dc4
Merge pull request #269 from mukhtharcm/feat/multi-account-roundrobin
feat: Multi-account OAuth with round-robin rotation
2026-01-06 06:13:19 +00:00
Peter Steinberger b5c604b7b7 fix: require slash for control commands 2026-01-06 07:05:17 +01:00
Peter Steinberger 7d896b5f67 fix: doctor memory hint 2026-01-06 06:01:24 +00:00
Shadow 91cb2c02a7
fix: allow optional reply body 2026-01-05 23:47:33 -06:00
Shadow 69f285c5ca
chore: fixed CI 2026-01-05 23:36:48 -06:00
Peter Steinberger b759cb6f37 feat(providers): normalize location parsing 2026-01-06 06:31:09 +01:00
Nacho Iacovino 255e77f530 feat(telegram): parse location and venue messages
- Add TelegramLocation, TelegramVenue, and TelegramMessageWithLocation types
- Add formatLocationMessage() to convert location/venue shares to text
- Add extractLocationData() for structured location access in ctxPayload
- Handle both raw location pins and venue shares (places with names)
- Include location in reply-to context for quoted messages

Location messages now appear as:
- [Location: lat, lon ±accuracy] for raw pins
- [Venue: Name - Address (lat, lon)] for places

ctxPayload includes LocationLat, LocationLon, LocationAccuracy,
VenueName, and VenueAddress fields for programmatic access.
2026-01-06 06:31:09 +01:00
Muhammed Mukhthar CM 18c7795ee0 feat: treat timeout as rate limit for profile rotation
Antigravity rate limits cause requests to hang indefinitely rather than
returning 429 errors. This change detects timeouts and treats them as
potential rate limits:

- Added timedOut flag to track timeout-triggered aborts
- Timeout now triggers profile cooldown + rotation
- Logs: "Profile X timed out (possible rate limit). Trying next account..."

This ensures automatic failover when Antigravity hangs due to rate limiting.
2026-01-06 05:20:01 +00:00
Muhammed Mukhthar CM ce6c7737c1 feat: add round-robin rotation and cooldown for auth profiles
Adds usage tracking to auth profiles for automatic rotation:

- ProfileUsageStats type with lastUsed, cooldownUntil, errorCount
- markAuthProfileUsed(): tracks successful usage, resets errors
- markAuthProfileCooldown(): applies exponential backoff (1/5/25/60min)
- isProfileInCooldown(): checks if profile should be skipped
- orderProfilesByMode(): now sorts by lastUsed (oldest first)

On auth/rate-limit failures, profiles are marked for cooldown before
rotation. On success, usage is recorded for round-robin ordering.

This enables automatic load distribution across multiple accounts
(e.g., Antigravity 5-hour rate limit windows).
2026-01-06 05:17:59 +00:00
Muhammed Mukhthar CM 06df6a955a feat: use email-based profile IDs for OAuth providers
Changes writeOAuthCredentials and applyAuthProfileConfig calls to use
the email from OAuth response as part of the profile ID instead of
hardcoded ":default".

This enables multiple accounts per provider - each login creates a
separate profile (e.g., google-antigravity:user@gmail.com) instead
of overwriting the same :default profile.

Affected files:
- src/commands/onboard-auth.ts (generic writeOAuthCredentials)
- src/commands/configure.ts (Antigravity flow)
- src/wizard/onboarding.ts (Antigravity flow)
2026-01-06 05:17:59 +00:00
Shadow 88cb13dc82
Auto-reply: fix typing stop race (#270) 2026-01-05 22:57:04 -06:00
Peter Steinberger 35a2140e48 fix: clean up poll merge 2026-01-06 04:51:05 +00:00
Peter Steinberger 0b27964693 feat: unify poll support
Co-authored-by: DBH <5251425+dbhurley@users.noreply.github.com>
2026-01-06 04:51:05 +00:00
Asleep 8880128ebf
Format messages so they work with Gemini API (#266)
* fix: Gemini stops working after one message in a session

* fix: small issue in test file

* test: cover google role-merge behavior

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-01-06 04:45:40 +00:00
DBH 2737e17c67
feat: Add WhatsApp poll support (#248)
Implements issue #123 - WhatsApp Poll Support

## Gateway Protocol
- Add `poll` RPC method with params: to, question, options (2-12), selectableCount

## ActiveWebListener
- Add `sendPoll(to, poll)` method to interface
- Implementation uses Baileys poll message type

## CLI Command
- `clawdbot poll --to <jid> -q <question> -o <opt1> -o <opt2> [-s count]`
- Supports --dry-run, --json, --verbose flags
- Validates 2-12 options

## Changes
- src/gateway/protocol/schema.ts: Add PollParamsSchema
- src/gateway/protocol/index.ts: Export validator and types
- src/web/active-listener.ts: Add sendPoll to interface
- src/web/inbound.ts: Implement sendPoll using Baileys
- src/web/outbound.ts: Add sendPollWhatsApp function
- src/gateway/server-methods/send.ts: Add poll handler
- src/commands/poll.ts: New CLI command
- src/cli/program.ts: Register poll command

Closes #123
2026-01-06 04:44:15 +00:00
Peter Steinberger ea6ee16461 chore: fix lint warnings 2026-01-06 05:41:24 +01:00
Peter Steinberger 77789cb9a8 fix: improve compaction queueing and oauth flows 2026-01-06 05:41:24 +01:00
Marcus Neves 9ab0b88ac6
feat(whatsapp,telegram): add groupPolicy config option (#216)
Co-authored-by: Marcus Neves <conhecendo.contato@gmail.com>
Co-authored-by: Shadow <hi@shadowing.dev>
2026-01-05 22:41:19 -06:00
Peter Steinberger 53c9feb597 test: cover slack thread reply routing 2026-01-06 05:11:06 +01:00
Steve Caldwell 7034d4f807 fix(slack): preserve thread context in auto-replies
When replying to a message in a Slack thread, the response now stays
in the thread instead of going to the channel root.

Only threads replies when the incoming message was already in a thread
(has thread_ts). Top-level messages get top-level replies.

Fixes #250
2026-01-06 05:09:04 +01:00
Ayaan Zaidi bd735182b6
feat(telegram): support media groups (multi-image messages) (#220) 2026-01-05 22:04:33 -06:00
VACInc fb2513e265
fix(discord): Use channel ID for DMs instead of user ID (#261)
Co-authored-by: VAC <vac@vacs-mac-mini.localdomain>
2026-01-05 22:02:33 -06:00
Peter Steinberger 13eb9c9ee9 refactor: centralize reply dispatch 2026-01-06 04:55:00 +01:00
Peter Steinberger 5946f4c341 test: extend typing idle coverage 2026-01-06 03:42:33 +00:00
Peter Steinberger 1a4f7d3388 feat: add ack reaction defaults 2026-01-06 03:28:47 +00:00
Peter Steinberger 58186aa56e test: cover typing idle gate 2026-01-06 03:28:47 +00:00
Peter Steinberger ca8f66f844 refactor: unify group allowlist policy 2026-01-06 04:27:51 +01:00
Ayaan Zaidi b1bb3ff6a6 feat: add reaction to acknowledge message in createTelegramBot 2026-01-06 03:21:56 +00:00
Peter Steinberger 9d656f4269 style: satisfy lint 2026-01-06 03:11:42 +00:00
Peter Steinberger d5f088978a fix: stop typing after dispatcher idle 2026-01-06 03:09:49 +00:00
Josh Palmer cbc39bd005
use process PATH for bash tool (#202)
what: default bash PATH to process.env.PATH

why: ensure Nix-provided tools on PATH inside sessions

tests: not run

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-01-06 03:05:21 +00:00
Peter Steinberger 20a361a3cf refactor: centralize agent timeout defaults 2026-01-06 02:48:44 +00:00
Martin Schürrer d83ca74c18
gateway: honor agent timeout for chat.send (#229)
Co-authored-by: clawd@msch <clawd@msch>
2026-01-06 02:45:02 +00:00
Peter Steinberger 9b5610aa45 style: format telegram bot test 2026-01-06 03:43:05 +01:00
Peter Steinberger 9623bd7763 fix: route agent CLI via gateway 2026-01-06 03:41:56 +01:00
Peter Steinberger 0398f684e7 fix: add gateway stop/restart commands 2026-01-06 03:25:32 +01:00
Peter Steinberger cc0ef4d012 fix(telegram): improve gif handling 2026-01-06 02:22:19 +00:00
Marcus Neves 67e1452f4a
Cron: normalize cron.add inputs + align channels (#256)
* fix: harden cron add and align channels

* fix: keep cron tool id params

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-01-06 02:09:48 +00:00
Peter Steinberger 00061b2fd3 fix: harden config form 2026-01-06 03:05:56 +01:00
Peter Steinberger 20705d1b37 fix: set codex oauth model default 2026-01-06 02:49:45 +01:00
Peter Steinberger b6ac2d860d fix: resolve embedded api key lookup 2026-01-06 02:49:44 +01:00
Peter Steinberger b30bae89ed feat: track compaction count + verbose notice 2026-01-06 02:49:03 +01:00
Peter Steinberger 3c6dea3ef3 style: format gmail watcher test 2026-01-06 01:46:59 +00:00
Peter Steinberger 55b33b4e69 fix: stop gmail watcher restart on bind error 2026-01-06 01:40:15 +00:00
Peter Steinberger 87f4efda8d fix: restore auth fallback ordering 2026-01-06 01:38:15 +00:00
Peter Steinberger 6f541d6304 fix: improve discord permission errors 2026-01-06 01:38:15 +00:00
Echo 162f8e9bb7
fix(discord): convert readMessages timestamps to local time (#240)
Co-authored-by: Cash Williams <cashwilliams@gmail.com>
2026-01-05 19:37:05 -06:00
Peter Steinberger b6ae376076 fix: gate reset auth and infer whatsapp sender 2026-01-06 02:23:55 +01:00
Peter Steinberger b56338171b feat: gate slash commands and add compact 2026-01-06 02:23:55 +01:00
Peter Steinberger 085c70a87b fix: prefer env keys unless profiles configured 2026-01-06 01:21:45 +00:00
Peter Steinberger 216a23ed08 fix: auto-migrate legacy config on CLI 2026-01-06 01:10:32 +00:00
Peter Steinberger e73573eaea fix: clean model config typing 2026-01-06 01:08:36 +00:00
Peter Steinberger b04c838c15 feat!: redesign model config + auth profiles 2026-01-06 00:56:58 +00:00
Peter Steinberger f7074ea45f test: cover logging defaults 2026-01-06 01:39:42 +01:00
Peter Steinberger d813e14950 chore: update mention gating docs and tests 2026-01-06 01:38:36 +01:00
Peter Steinberger 811ec8b78b fix: unify mention gating across providers 2026-01-06 01:32:17 +01:00
Peter Steinberger 5356adba8f fix: keep Slack thread replies in thread 2026-01-06 01:09:25 +01:00
Peter Steinberger 291c6f3b60 test: cover WhatsApp DM senderE164 2026-01-06 00:55:41 +01:00
Xin a6a45f4b84
fix(whatsapp): populate senderE164 for direct chats to enable owner commands (#247) 2026-01-05 23:54:35 +00:00
Peter Steinberger a4fdfc2414 chore: fix redaction lint 2026-01-06 00:42:23 +01:00
Peter Steinberger 8be168b180 fix: redact sensitive tokens in tool summaries 2026-01-06 00:41:12 +01:00
Peter Steinberger 20e00eb89b fix: normalize unknown prompt errors 2026-01-05 23:05:57 +00:00
Peter Steinberger ac3dedaa1b feat: standardize timestamps to UTC 2026-01-05 23:03:59 +00:00
Peter Steinberger f790f3f3ba
fix/heartbeat ok delivery filter (#246)
* cron: skip delivery for HEARTBEAT_OK responses

When an isolated cron job has deliver:true, skip message delivery if the
response is just HEARTBEAT_OK (or contains HEARTBEAT_OK at edges with
short remaining content <= 30 chars). This allows cron jobs to silently
ack when nothing to report but still deliver actual content when there
is something meaningful to say.

Media is still delivered even if text is HEARTBEAT_OK, since the
presence of media indicates there's something to share.

* fix(heartbeat): make ack padding configurable

* chore(deps): update to latest

---------

Co-authored-by: Josh Lehman <josh@martian.engineering>
2026-01-05 22:52:13 +00:00
Josh Lehman dae7f560a5
cron: skip delivery for HEARTBEAT_OK responses (#238)
When an isolated cron job has deliver:true, skip message delivery if the
response is just HEARTBEAT_OK (or contains HEARTBEAT_OK at edges with
short remaining content <= 30 chars). This allows cron jobs to silently
ack when nothing to report but still deliver actual content when there
is something meaningful to say.

Media is still delivered even if text is HEARTBEAT_OK, since the
presence of media indicates there's something to share.
2026-01-05 22:16:28 +00:00
Peter Steinberger 53bf8b7b80 fix: avoid duplicate missing auth label 2026-01-05 23:00:37 +01:00
CI d9cdf3b8ac fix(model): treat quota errors as rate limits 2026-01-05 21:34:08 +00:00
CI c627efce3e fix(model): retry with supported thinking level 2026-01-05 21:34:08 +00:00
CI 5622dfe86b fix: retry model fallback on rate limits 2026-01-05 21:34:08 +00:00
Peter Steinberger 1b6c8178ae style: apply biome formatting 2026-01-05 21:21:53 +00:00
Tobias Bischoff de153a40d0 Onboard: auto-enable systemd lingering on Linux 2026-01-05 21:20:05 +00:00
Peter Steinberger c75b2a7067 refactor: unify reply dispatch across providers 2026-01-05 19:43:54 +01:00
Peter Steinberger cc790f2c84 docs(agent): annotate stream invariants 2026-01-05 18:10:03 +00:00
Peter Steinberger 86ad703f53 refactor(agent): extract block chunker + tool adapter 2026-01-05 18:05:40 +00:00
Peter Steinberger 7c89ce93b5 fix(agent): align tools + preserve indentation 2026-01-05 17:55:20 +00:00
Peter Steinberger ad6bec4612 fix: enable systemd lingering for gateway 2026-01-05 18:38:43 +01:00
Peter Steinberger 0fb30db819 test: expand fenced block chunking coverage 2026-01-05 18:38:43 +01:00
Peter Steinberger 22105c8496 fix(agent): finalize block chunking 2026-01-05 17:22:29 +00:00
Peter Steinberger b7e708c764 fix(chat): stabilize web UI tool runs 2026-01-05 17:22:29 +00:00
Peter Steinberger 86c404c48b chore: fix reply commands lint 2026-01-05 18:16:39 +01:00
Julian Engel 110e2255c4 fix: pass custom tools via customTools parameter to pi-coding-agent SDK
The SDK's tools parameter only accepts built-in tools (read, bash, edit, write).
Custom clawdbot tools (browser, canvas, nodes, cron, etc.) were being filtered
out, causing 'Tool not found' errors at runtime.

Split tools into built-in and custom, passing them via the correct parameters.
2026-01-05 17:00:06 +00:00
Peter Steinberger 55e4e76d43 fix: preserve fenced markdown in block streaming 2026-01-05 17:53:53 +01:00
Peter Steinberger 7f3f73af1c fix: show model auth in status 2026-01-05 15:50:18 +01:00
Peter Steinberger bf6aad1965 fix(ci): format directive-handling 2026-01-05 14:34:55 +00:00
Peter Steinberger 0c37f27a4a fix: show /model auth source 2026-01-05 14:14:26 +00:00
Peter Steinberger cffbe79077 fix: add /model list alias 2026-01-05 14:11:33 +00:00
Peter Steinberger bb959684fe fix(tui): support pi-tui 0.36 key exports 2026-01-05 13:59:50 +00:00
Peter Steinberger 8e8d07cbf4 fix(ci): satisfy formatter checks 2026-01-05 13:55:53 +00:00
Peter Steinberger 5f4936dce5 fix(wizard): type OAuth provider login 2026-01-05 13:55:46 +00:00
Peter Steinberger a9bcf88bfa refactor(tui): use key helper predicates 2026-01-05 13:55:43 +00:00
Peter Steinberger f24fe4e9cd fix(whatsapp): reconnect on crypto unhandled rejection 2026-01-05 13:55:37 +00:00
Peter Steinberger 7619534bc0 feat(groups): resolve requireMention for discord/slack 2026-01-05 13:55:32 +00:00
Peter Steinberger ce68d82dfa fix: widen /model key masking 2026-01-05 13:50:45 +00:00
Peter Steinberger 5163886694 fix: show auth in /model list 2026-01-05 13:49:25 +00:00
Peter Steinberger 724354b9f0 fix: make tool list dynamic in system prompt 2026-01-05 06:36:24 +00:00
Peter Steinberger 79561d07a0 fix: allow openai-codex in onboarding types 2026-01-05 07:33:33 +01:00
Peter Steinberger 5431a9c692 fix: clean status + help + mid alias 2026-01-05 07:24:51 +01:00
Peter Steinberger 5aebc07369 chore: remove stale a2ui bundle hash 2026-01-05 06:17:06 +00:00
Peter Steinberger 9be1a14a08 fix: resolve agent dir in onboarding 2026-01-05 07:12:13 +01:00
Peter Steinberger 17ef7b3b0e fix: status runtime + help 2026-01-05 07:07:17 +01:00
Peter Steinberger 1545ac0003 chore: update a2ui bundle hash 2026-01-05 06:39:08 +01:00
Peter Steinberger f3cb41511d feat: add openai codex oauth 2026-01-05 06:31:45 +01:00
Peter Steinberger 995f5959af fix: stage sandbox media for inbound attachments 2026-01-05 06:18:11 +01:00
Peter Steinberger a7d33c06f9 refactor: align agent lifecycle 2026-01-05 05:55:02 +01:00
Peter Steinberger bcdaba1d48 chore: format custom editor 2026-01-05 05:32:30 +01:00
Peter Steinberger 870473be85 chore: update deps 2026-01-05 05:27:58 +01:00
Peter Steinberger 2eb78b8da7 fix: resolve qrcode ESM import for Node 25 2026-01-05 03:47:57 +01:00
Peter Steinberger 93bb0257f0 fix: include sessions in npm pack and update qrcode import 2026-01-05 03:28:25 +01:00
Peter Steinberger deba1b6739 style: format daemon program args test 2026-01-05 02:54:08 +01:00
Peter Steinberger aab98a6d18 test: fix daemon program args fs mocks 2026-01-05 02:51:56 +01:00
Peter Steinberger 849a008f34 test: avoid max port in browser server tests 2026-01-05 02:50:48 +01:00
Peter Steinberger 8791e46cf3 fix: resolve npx gateway daemon install 2026-01-05 02:48:25 +01:00
Peter Steinberger d92a9e351e style: fix linting order and formatting 2026-01-05 02:33:59 +01:00
Peter Steinberger a1acd7dae8 chore: add qrcode-terminal vendor module stubs 2026-01-05 02:33:55 +01:00
Peter Steinberger 67420e9a81 fix: allow group activation for allowFrom senders 2026-01-05 02:33:51 +01:00
Peter Steinberger e4335ea094 fix: bundle qr renderer in relay 2026-01-05 02:19:49 +01:00
Peter Steinberger 0c632f4855 fix: prefer tailnet IP for local gateway calls 2026-01-05 02:19:26 +01:00
Peter Steinberger a322075764 fix: use id for cron tool params 2026-01-05 02:15:11 +01:00
Peter Steinberger 359cb66e68 fix: allow wildcard control commands 2026-01-05 02:06:18 +01:00
Peter Steinberger 00370139a5 docs: clarify derived port mapping 2026-01-05 02:03:29 +01:00
Peter Steinberger 17422608b2 fix: gate /activation to owners in groups 2026-01-05 02:03:29 +01:00
Peter Steinberger 85549ac3b6 fix: gate group activation by owner 2026-01-05 00:48:16 +00:00
Peter Steinberger 1bad96aa2b style: tidy auto-reply imports and formatting 2026-01-05 01:46:16 +01:00
Peter Steinberger b0dcdc4982 fix: avoid mixing ?? and || in discord monitor 2026-01-05 01:46:16 +01:00
Shadow 13d39b8fb1
Fix discord/slack monitor compile errors 2026-01-04 18:44:19 -06:00
Peter Steinberger 50d26d827e fix: avoid duplicate senderName in slack monitor 2026-01-05 00:43:31 +00:00
Peter Steinberger d58828ebd7 test: relax timeouts for slow runs 2026-01-05 01:36:30 +01:00
Jake 3f40f4ab54 style: fix lint issues 2026-01-05 01:36:30 +01:00
Jake 65a55b97e0 WhatsApp: mark offline/history messages as read 2026-01-05 01:36:29 +01:00
Peter Steinberger 852f947b44 fix: unify control command handling 2026-01-05 01:31:36 +01:00
Peter Steinberger c6de1b1f7d feat: add --dev/--profile CLI profiles 2026-01-05 01:27:13 +01:00
Peter Steinberger f601dac30d style: tidy tool schema normalization 2026-01-05 01:27:13 +01:00
Peter Steinberger 39e482414a chore: apply upstream autostash 2026-01-05 00:26:52 +00:00
Peter Steinberger bcdfe461d4 fix(ci): resolve lint and docs build failures 2026-01-05 00:17:14 +00:00
Peter Steinberger 2899a986a8 feat(config): add default model shorthands 2026-01-05 01:11:29 +01:00
Peter Steinberger 7a63b4995b feat: opt-in login shell env fallback 2026-01-05 01:11:29 +01:00
Peter Steinberger 7a36e6fcd9 fix(discord): avoid duplicate block replies 2026-01-05 01:11:29 +01:00
Peter Steinberger 77b19643e2 fix: load global .env fallback 2026-01-05 01:11:29 +01:00
Josh Palmer aa45f512f4 fix sessions dir from state env
what: use CLAWDBOT_STATE_DIR/CLAWDIS_STATE_DIR for session transcripts

why: isolate multi-instance gateways

tests: not run
2026-01-05 00:51:11 +01:00
Peter Steinberger 4963432777 fix(discord): avoid duplicate replies on repeated message_end 2026-01-05 00:35:42 +01:00
Peter Steinberger 435edaf997 fix: OpenAI tool schema compatibility 2026-01-05 00:15:55 +01:00
Jake 946b32c842
fix(whatsapp): suppress typing during heartbeats
- Prevent typing indicator during heartbeat runs
- Add regression tests

Co-authored-by: Jake <mcinteerj@gmail.com>
2026-01-04 23:03:36 +00:00
Peter Steinberger 4dd515b65f fix(tools): honor agent tool denylist without sandbox 2026-01-05 00:02:14 +01:00
Peter Steinberger 1657c5e3d2 fix: route system events per session 2026-01-04 22:11:04 +01:00
Peter Steinberger 2ceceb8c25 style(ts): normalize type-only imports 2026-01-04 21:56:16 +01:00
Peter Steinberger 0faa200924 fix(onboarding): auto-build Control UI assets 2026-01-04 21:53:23 +01:00
Peter Steinberger 78998dba9e feat: add image model config + tool 2026-01-04 19:35:49 +01:00
Peter Steinberger 0716a624a8 chore(lint): apply biome fixes 2026-01-04 19:08:22 +01:00
Peter Steinberger e005dcb8e7 fix(oauth): derive oauth.json from state dir 2026-01-04 19:08:13 +01:00
Peter Steinberger d85f91d247 feat: guide control ui access without gui 2026-01-04 18:49:36 +01:00
Shadow 50cecd8210
Discord: remove duplicate message ids 2026-01-04 11:36:18 -06:00
Peter Steinberger 2110cac5d6 fix(cli): add config alias and reduce probe noise 2026-01-04 17:23:34 +00:00
Peter Steinberger 5d17b84e8a test(gateway): allow webchat chat.send without node 2026-01-04 17:12:49 +00:00
Peter Steinberger 2694e59ba6 fix(gateway): allow Control UI chat without node 2026-01-04 17:12:49 +00:00
Peter Steinberger ff46f8ce58 chore: format models CLI 2026-01-04 18:11:41 +01:00
Peter Steinberger 734bb6b4fd feat: add models scan and fallbacks 2026-01-04 17:57:52 +01:00
Cash Williams 64e656af82 fix: default elevated level to 'off' when not allowed
When elevatedAllowed is false (e.g., for heartbeat surface which isn't
in any allowFrom list), the elevated level was incorrectly defaulting
to 'on', causing bash commands to fail with 'elevated is not available'.

Now defaults to 'off' when elevated isn't allowed, so bash works
normally without trying to use elevated mode.

Fixes: https://github.com/clawdbot/clawdbot/issues/181
2026-01-04 17:36:14 +01:00
Clawd 17665d1732 fix(cron): pass 'id' instead of 'jobId' to gateway
The cron tool was passing { jobId } to the gateway for update/remove/run/runs
actions, but the gateway protocol schema expects { id }. This caused validation
errors when trying to update or remove cron jobs via the tool.

Fixes the parameter name while keeping the external tool API unchanged (still
accepts 'jobId' from callers).
2026-01-04 17:18:29 +01:00
Peter Steinberger 718299b25a feat(doctor): repair sandbox images 2026-01-04 16:02:24 +00:00
Peter Steinberger 5f09d801d0 feat(doctor): migrate legacy Clawdis config 2026-01-04 15:40:06 +00:00
Peter Steinberger 65ad956ab4 feat(daemon): add legacy Clawdis service cleanup 2026-01-04 15:40:06 +00:00
Peter Steinberger 026a25d164 chore: lint and format cleanup 2026-01-04 16:24:17 +01:00
Peter Steinberger e8de7d083d feat: update onboard ASCII art to seafood shack lobster theme 2026-01-04 16:24:17 +01:00
Peter Steinberger 8f53e9093d test: align google-shared expectations 2026-01-04 15:02:42 +00:00
Peter Steinberger 30d5511058 test: add config for gateway sigterm 2026-01-04 14:59:49 +00:00
Peter Steinberger c6b8235862 style: format tests and helpers 2026-01-04 14:57:57 +00:00
Peter Steinberger 557aa74ee8 test: update google-shared expectations 2026-01-04 14:57:57 +00:00
Peter Steinberger 246adaa119 chore: rename project to clawdbot 2026-01-04 14:38:51 +00:00
Peter Steinberger d48dc71fa4 feat: add canvasHost liveReload option 2026-01-04 15:22:47 +01:00
Peter Steinberger 1e555e693a fix: dedupe canvas host watcher 2026-01-04 15:15:46 +01:00