switchroom 0.13.65 → 0.14.1

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.
Files changed (30) hide show
  1. package/dist/agent-scheduler/index.js +80 -80
  2. package/dist/auth-broker/index.js +96 -81
  3. package/dist/cli/drive-write-pretool.mjs +10 -10
  4. package/dist/cli/notion-write-pretool.mjs +82 -82
  5. package/dist/cli/skill-validate-pretool.mjs +72 -72
  6. package/dist/cli/switchroom.js +1883 -1479
  7. package/dist/host-control/main.js +149 -149
  8. package/dist/vault/approvals/kernel-server.js +82 -82
  9. package/dist/vault/broker/server.js +83 -83
  10. package/package.json +1 -1
  11. package/profiles/_shared/telegram-style.md.hbs +1 -1
  12. package/telegram-plugin/auth-snapshot-format.ts +47 -1
  13. package/telegram-plugin/dist/bridge/bridge.js +112 -112
  14. package/telegram-plugin/dist/gateway/gateway.js +1226 -696
  15. package/telegram-plugin/dist/server.js +160 -160
  16. package/telegram-plugin/gateway/boot-card.ts +100 -0
  17. package/telegram-plugin/gateway/config-snapshot.ts +274 -0
  18. package/telegram-plugin/gateway/gateway.ts +256 -36
  19. package/telegram-plugin/operator-events.ts +2 -10
  20. package/telegram-plugin/quota-watch.ts +276 -0
  21. package/telegram-plugin/tests/auth-snapshot-format.test.ts +133 -1
  22. package/telegram-plugin/tests/boot-card-render.test.ts +93 -0
  23. package/telegram-plugin/tests/config-snapshot.test.ts +409 -0
  24. package/telegram-plugin/tests/operator-events.test.ts +12 -6
  25. package/telegram-plugin/tests/quota-watch.test.ts +366 -0
  26. package/telegram-plugin/tests/tool-activity-summary.test.ts +66 -0
  27. package/telegram-plugin/tests/turn-flush-safety.test.ts +48 -0
  28. package/telegram-plugin/tool-activity-summary.ts +137 -0
  29. package/telegram-plugin/turn-flush-safety.ts +47 -0
  30. package/telegram-plugin/uat/assertions.ts +4 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "switchroom",
3
- "version": "0.13.65",
3
+ "version": "0.14.1",
4
4
  "description": "Run Claude Code 24/7 on your Claude Pro/Max subscription over Telegram. Open-source alternative to OpenClaw and NanoClaw — no API keys.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,7 +17,7 @@ The one thing to avoid is **spam**: a reply on every tool call, on a cadence, or
17
17
  - **`reply`** is the default. Use for acks, mid-turn updates, sub-agent handbacks, final answers. Pass `disable_notification: true` mid-turn.
18
18
  - **`stream_reply`** is for content whose final answer benefits from streaming character-by-character (long prose, code blocks). First call sends fresh; subsequent calls edit (no ping until `done=true`). Don't use it just to "show progress" — that's what `reply` is for.
19
19
 
20
- The 👀→🤔→🔥→👍 status reaction and the typing indicator are *ambient* liveness — they tell the user the agent is alive and working, automatically. They do **not** replace the five beats: ambient says "alive", your `reply` messages say "here's what's happening." Different layers; both run.
20
+ The 👀→🤔→✍→👍 status reaction and the typing indicator are *ambient* liveness — they tell the user the agent is alive and working, automatically. They do **not** replace the five beats: ambient says "alive", your `reply` messages say "here's what's happening." Different layers; both run.
21
21
 
22
22
  **Reactions ON your replies.** Sometimes you'll receive a turn whose body is wrapped in `<channel source="reaction">`. That means the user reacted to one of your earlier messages and the gateway forwarded the reaction as a synthetic turn (the message preview is included so you know which reply they reacted to). 👎 / ❌ are stop signals — pause, reconsider the approach, ask what's off. 👍 / ✅ are acknowledgements — keep going if mid-task, no extra reply needed. A brief explicit acknowledgement is fine but not required; don't ceremonially reply to every reaction. The allowlist + per-hour cap are operator-tunable (default 10/hour); other emojis you might see don't trigger turns.
23
23
 
@@ -19,7 +19,7 @@
19
19
  */
20
20
 
21
21
  import type { QuotaResult, QuotaUtilization } from './quota-check.js';
22
- import type { AccountState, ListStateData } from '../src/auth/broker/client.js';
22
+ import type { AccountState, LastQuotaSnapshot, ListStateData } from '../src/auth/broker/client.js';
23
23
 
24
24
  // ── shared types ─────────────────────────────────────────────────────
25
25
 
@@ -610,3 +610,49 @@ export function buildSnapshotsFromState(
610
610
  }
611
611
  return out;
612
612
  }
613
+
614
+ /**
615
+ * Convert a broker-side `LastQuotaSnapshot` (dates as ISO strings) into a
616
+ * `QuotaUtilization` (dates as `Date | null`). Returns null when the
617
+ * input snapshot is absent or null (no probe has run since broker start).
618
+ *
619
+ * Used by the quota-watch loop to build `AccountSnapshot[]` from cached
620
+ * broker state without triggering a live Anthropic network call.
621
+ */
622
+ export function reviveLastQuota(snap: LastQuotaSnapshot | null | undefined): QuotaUtilization | null {
623
+ if (!snap) return null;
624
+ return {
625
+ fiveHourUtilizationPct: snap.fiveHourUtilizationPct,
626
+ sevenDayUtilizationPct: snap.sevenDayUtilizationPct,
627
+ fiveHourResetAt: snap.fiveHourResetAt ? new Date(snap.fiveHourResetAt) : null,
628
+ sevenDayResetAt: snap.sevenDayResetAt ? new Date(snap.sevenDayResetAt) : null,
629
+ representativeClaim: snap.representativeClaim,
630
+ overageStatus: snap.overageStatus,
631
+ overageDisabledReason: snap.overageDisabledReason,
632
+ };
633
+ }
634
+
635
+ /**
636
+ * Build AccountSnapshot[] from broker listState using only the
637
+ * broker's in-memory last_quota cache — no live Anthropic probe.
638
+ * Accounts with no cached snapshot will have `quota: null`, causing
639
+ * `classifyHealth` to return 'unknown' and the quota-watch loop to skip them.
640
+ *
641
+ * This is the cheap classification path for the 15-minute poll loop.
642
+ * The live probeQuota path (`buildSnapshotsFromState`) is reserved for
643
+ * user-initiated /auth commands and notification body enrichment.
644
+ */
645
+ export function buildSnapshotsFromCachedState(
646
+ state: ListStateData,
647
+ ): AccountSnapshot[] {
648
+ return state.accounts.map((acc) => {
649
+ const lq = acc.last_quota ?? null;
650
+ return {
651
+ label: acc.label,
652
+ isActive: acc.label === state.active,
653
+ quota: reviveLastQuota(lq),
654
+ quotaError: lq ? undefined : 'no cached quota (no probe since broker start)',
655
+ expiresAtMs: acc.expiresAt,
656
+ };
657
+ });
658
+ }