Commit Graph
12 Commits
Author SHA1 Message Date
KoshkoshinskandClaude Opus 4.6 9a955b9b01 docs(v2-checklist): plan main/non-main -> owner/admin refactor
Pairing-code registration applies to every Telegram group once the privileged
"main chat" identity goes away.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 12:49:22 +00:00
Koshkoshinsk ae88d2b7c2 fix(telegram): retry adapter setup on transient network errors
Cold-start DNS/network hiccups can fail the adapter's first deleteWebhook or
getMe call, leaving the channel silently dead while the service stays up.
Wrap bridge.setup in an exponential-backoff retry (5 attempts) — if the
network is truly down we surface it instead of hanging forever.

Lives in telegram.ts so the chat-sdk bridge stays generic; other channels
can opt in by copying the small helper if they hit the same issue.
2026-04-13 12:27:45 +00:00
KoshkoshinskandClaude Opus 4.6 65afcdc946 feat(telegram-pairing): surface wrong-code attempts + auto-regen with retry cap
- createPairing now replaces any existing pending pairing for the same intent
  (replace-by-default; no "two pending codes for one intent" state)
- tryConsume records each attempt on pending records (capped at 10); a
  wrong code invalidates the pairing immediately (one attempt per code)
- waitForPairing gains onAttempt callback for misses and rejects with a
  distinct "invalidated by wrong code" message so callers can distinguish
  TTL expiry from user-error
- pair-telegram emits PAIR_TELEGRAM_ATTEMPT on misses and auto-regenerates
  the pairing up to 5 times, emitting PAIR_TELEGRAM_NEW_CODE for each
- Skill docs updated so the host Claude knows to show new codes and
  offer another batch on max-regenerations-exceeded

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 12:27:09 +00:00
KoshkoshinskandClaude Opus 4.6 2454444f2e feat(telegram-pairing): accept bare 4-digit codes
Require the message to be exactly the 4 digits (optionally prefixed by
@botname). Loose matches like "my pin is 0349" are rejected to avoid false
positives from chat traffic that happens to contain a 4-digit number.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 12:27:06 +00:00
Koshkoshinsk 2017589683 feat(telegram): self-contained pairing for chat ownership verification
BotFather issues bot tokens with no user binding, so anyone who guesses the
bot's username can DM it and get registered as a channel. Pairing closes that
gap: setup issues a one-time 4-digit code, the operator echoes it back from
the chat they want to register, and the inbound interceptor binds
admin_user_id before the message reaches the router.

- src/channels/telegram-pairing.ts: JSON-backed store with createPairing,
  tryConsume, getStatus, waitForPairing (fs.watch + poll fallback)
- src/channels/telegram.ts: wraps bridge.setup with an onInbound interceptor
  that consumes pairing codes and upserts messaging_groups
- setup/pair-telegram.ts: CLI step issues a code and waits up to 5 min for
  the operator to echo it back, emitting PLATFORM_ID/IS_GROUP/ADMIN_USER_ID
- Skill docs: /setup reorders mounts -> service -> wire (pairing needs a
  live polling adapter); /manage-channels and /add-telegram-v2 use pairing
  instead of asking the user to discover chat IDs

All other channels still bind admin via install-time identity (OAuth/QR/token);
pairing is Telegram-only. The bridge, router, and other adapters are untouched.
2026-04-13 12:27:02 +00:00
KoshkoshinskandClaude Opus 4.6 b7434b8a76 fix: use explicit Read tool directive for diagnostics instructions
The previous wording ("Send diagnostics data by following ...") was too
passive — Claude treated the backtick-quoted path as informational rather
than an action, so the diagnostics file was never actually read and the
PostHog prompt was silently skipped.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 14:07:59 +00:00
KoshkoshinskandClaude Opus 4.6 d622a79fe2 fix: suppress spurious chat message on script skip
When a script returns wakeAgent=false, set result to null so the host
doesn't forward an internal status string to the user's chat.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 11:41:25 +00:00
KoshkoshinskandClaude Opus 4.6 4f7efd3c67 fix: make diagnostics step explicit so Claude actually follows it
The diagnostics section used a markdown link that Claude never resolved,
so the prompt was silently skipped. Replace with a numbered step (setup)
and mandatory final step (update-nanoclaw) that instructs Claude to use
the Read tool on the full file path. Update opt-out instructions to
match the renamed section headings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 14:37:47 +00:00
KoshkoshinskandClaude Opus 4.6 8c1d5598ba fix: strip PostHog internal fields from dry-run output
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 01:24:32 +02:00
KoshkoshinskandClaude Opus 4.6 3747dfeacc fix: also strip distinct_id from dry-run output
Ephemeral UUID is harmless but showing it to users creates unnecessary
doubt about whether they're being tracked.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 01:24:32 +02:00
KoshkoshinskandClaude Opus 4.6 33874de175 fix: strip api_key from dry-run output shown to user
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 01:24:32 +02:00
KoshkoshinskandClaude Opus 4.6 f04a8955aa feat: add opt-in diagnostics via PostHog
Per-event consent diagnostics that sends anonymous install/update/skill data
to PostHog. Conflict filenames are gated against upstream. Supports --dry-run
to show exact payload before sending, and "never ask again" opt-out via state.yaml.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 01:24:32 +02:00