switchroom 0.14.0 → 0.14.2
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/dist/auth-broker/index.js +16 -1
- package/dist/cli/switchroom.js +1082 -873
- package/dist/host-control/main.js +1 -1
- package/package.json +1 -1
- package/profiles/_shared/telegram-style.md.hbs +1 -1
- package/telegram-plugin/auth-snapshot-format.ts +47 -1
- package/telegram-plugin/dist/gateway/gateway.js +983 -537
- package/telegram-plugin/gateway/boot-card.ts +100 -0
- package/telegram-plugin/gateway/config-snapshot.ts +274 -0
- package/telegram-plugin/gateway/gateway.ts +235 -20
- package/telegram-plugin/operator-events.ts +2 -10
- package/telegram-plugin/quota-watch.ts +276 -0
- package/telegram-plugin/tests/auth-snapshot-format.test.ts +133 -1
- package/telegram-plugin/tests/boot-card-render.test.ts +93 -0
- package/telegram-plugin/tests/config-snapshot.test.ts +409 -0
- package/telegram-plugin/tests/operator-events.test.ts +12 -6
- package/telegram-plugin/tests/quota-watch.test.ts +366 -0
- package/telegram-plugin/tests/tool-activity-summary.test.ts +45 -0
- package/telegram-plugin/tests/turn-flush-safety.test.ts +48 -0
- package/telegram-plugin/tool-activity-summary.ts +47 -0
- package/telegram-plugin/turn-flush-safety.ts +47 -0
- package/telegram-plugin/uat/assertions.ts +4 -4
|
@@ -21276,7 +21276,7 @@ class HostdServer {
|
|
|
21276
21276
|
if (req.args.deep) {
|
|
21277
21277
|
PROBES.push({
|
|
21278
21278
|
name: "auth_live",
|
|
21279
|
-
cmd: "
|
|
21279
|
+
cmd: "python3 -c 'import json,sys,time,re;" + 'c=json.load(open("/state/agent/.claude/.credentials.json"));' + 'o=c.get("claudeAiOauth",{});' + 't=o.get("accessToken","");' + 'sys.exit(0 if re.match(r"sk-ant-oat\\d+-",t)' + ' and ("expiresAt" not in o or o["expiresAt"]>time.time()*1000)' + " else 1)'"
|
|
21280
21280
|
});
|
|
21281
21281
|
}
|
|
21282
21282
|
if (!running) {
|
package/package.json
CHANGED
|
@@ -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
|
|
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
|
+
}
|