switchroom 0.15.45 → 0.16.5
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/agent-scheduler/index.js +56 -15
- package/dist/auth-broker/index.js +383 -97
- package/dist/cli/autoaccept-poll.js +4842 -35
- package/dist/cli/drive-write-pretool.mjs +7 -4
- package/dist/cli/notion-write-pretool.mjs +35 -4
- package/dist/cli/self-improve-apply-guard-pretool.mjs +626 -0
- package/dist/cli/self-improve-stop.mjs +428 -0
- package/dist/cli/switchroom.js +2894 -841
- package/dist/host-control/main.js +2685 -207
- package/dist/vault/approvals/kernel-server.js +7453 -7413
- package/dist/vault/broker/server.js +11428 -11388
- package/examples/minimal.yaml +1 -0
- package/examples/switchroom.yaml +1 -0
- package/package.json +3 -3
- package/profiles/_base/start.sh.hbs +97 -1
- package/profiles/_shared/execution-discipline.md.hbs +18 -0
- package/profiles/default/CLAUDE.md.hbs +0 -19
- package/telegram-plugin/.claude-plugin/plugin.json +2 -2
- package/telegram-plugin/answer-stream-flag.ts +12 -49
- package/telegram-plugin/answer-stream.ts +5 -150
- package/telegram-plugin/auth-snapshot-format.ts +280 -48
- package/telegram-plugin/auto-fallback-fleet.ts +44 -1
- package/telegram-plugin/context-exhaustion.ts +12 -0
- package/telegram-plugin/demo-mask.ts +154 -0
- package/telegram-plugin/dist/bridge/bridge.js +55 -12
- package/telegram-plugin/dist/gateway/gateway.js +2938 -977
- package/telegram-plugin/dist/server.js +55 -12
- package/telegram-plugin/docs/waiting-ux-spec.md +2 -2
- package/telegram-plugin/draft-stream.ts +47 -410
- package/telegram-plugin/final-answer-detect.ts +17 -12
- package/telegram-plugin/fleet-fallback-resume.ts +131 -0
- package/telegram-plugin/format.ts +56 -19
- package/telegram-plugin/gateway/auth-add-flow.ts +332 -127
- package/telegram-plugin/gateway/auth-broker-client.ts +2 -2
- package/telegram-plugin/gateway/auth-command.ts +70 -14
- package/telegram-plugin/gateway/clean-shutdown-marker.ts +44 -0
- package/telegram-plugin/gateway/config-approval-handler.test.ts +91 -4
- package/telegram-plugin/gateway/config-approval-handler.ts +94 -13
- package/telegram-plugin/gateway/current-turn-map.ts +188 -0
- package/telegram-plugin/gateway/disconnect-flush.ts +3 -1
- package/telegram-plugin/gateway/effort-command.ts +8 -3
- package/telegram-plugin/gateway/emission-authority.ts +369 -0
- package/telegram-plugin/gateway/feed-open-gate.ts +292 -0
- package/telegram-plugin/gateway/gateway.ts +1857 -292
- package/telegram-plugin/gateway/inject-handler.test.ts +2 -1
- package/telegram-plugin/gateway/model-command.ts +115 -4
- package/telegram-plugin/gateway/ms365-write-approval.test.ts +4 -4
- package/telegram-plugin/gateway/represent-guard.ts +72 -0
- package/telegram-plugin/gateway/status-surface-log.test.ts +5 -4
- package/telegram-plugin/gateway/status-surface-log.ts +14 -3
- package/telegram-plugin/history.ts +33 -11
- package/telegram-plugin/hooks/repo-context-pretool.mjs +26 -0
- package/telegram-plugin/hooks/subagent-tracker-posttool.mjs +5 -0
- package/telegram-plugin/hooks/subagent-tracker-pretool.mjs +8 -0
- package/telegram-plugin/hooks/tool-label-pretool.mjs +39 -15
- package/telegram-plugin/issues-card.ts +4 -0
- package/telegram-plugin/model-unavailable.ts +124 -0
- package/telegram-plugin/narrative-dedup.ts +69 -0
- package/telegram-plugin/over-ping-safety-net.ts +70 -4
- package/telegram-plugin/package.json +3 -3
- package/telegram-plugin/pending-work-progress.ts +12 -0
- package/telegram-plugin/permission-rule.ts +32 -5
- package/telegram-plugin/permission-title.ts +152 -9
- package/telegram-plugin/quota-check.ts +13 -0
- package/telegram-plugin/quota-watch.ts +135 -7
- package/telegram-plugin/registry/turns-schema.test.ts +24 -0
- package/telegram-plugin/registry/turns-schema.ts +9 -0
- package/telegram-plugin/runtime-metrics.ts +13 -0
- package/telegram-plugin/session-tail.ts +96 -11
- package/telegram-plugin/silence-poke.ts +170 -24
- package/telegram-plugin/slot-banner-driver.ts +3 -0
- package/telegram-plugin/status-no-truncate.ts +44 -0
- package/telegram-plugin/status-reactions.ts +20 -3
- package/telegram-plugin/stream-controller.ts +4 -23
- package/telegram-plugin/stream-reply-handler.ts +6 -24
- package/telegram-plugin/streaming-metrics.ts +91 -0
- package/telegram-plugin/subagent-watcher.ts +212 -66
- package/telegram-plugin/tests/activity-ever-opened-sticky.test.ts +47 -0
- package/telegram-plugin/tests/answer-stream-dedup.test.ts +9 -26
- package/telegram-plugin/tests/answer-stream-flag.test.ts +25 -58
- package/telegram-plugin/tests/answer-stream-silent-markers.test.ts +41 -51
- package/telegram-plugin/tests/answer-stream.test.ts +2 -411
- package/telegram-plugin/tests/auth-add-flow.test.ts +488 -253
- package/telegram-plugin/tests/auth-command-format2.test.ts +71 -1
- package/telegram-plugin/tests/auth-snapshot-format.test.ts +376 -6
- package/telegram-plugin/tests/auto-fallback-fleet.test.ts +120 -0
- package/telegram-plugin/tests/cross-turn-card-gate.test.ts +424 -0
- package/telegram-plugin/tests/demo-mask.test.ts +127 -0
- package/telegram-plugin/tests/draft-stream.test.ts +0 -827
- package/telegram-plugin/tests/emission-authority-card-drain-gate.test.ts +236 -0
- package/telegram-plugin/tests/emission-authority-facade.test.ts +488 -0
- package/telegram-plugin/tests/emission-authority-open-gate.test.ts +179 -0
- package/telegram-plugin/tests/emission-authority-ping-gate.test.ts +395 -0
- package/telegram-plugin/tests/emission-determinism-wiring.test.ts +177 -0
- package/telegram-plugin/tests/feed-heartbeat-liveness-open.test.ts +146 -0
- package/telegram-plugin/tests/feed-open-gate.test.ts +259 -0
- package/telegram-plugin/tests/feed-survival.test.ts +526 -0
- package/telegram-plugin/tests/fleet-fallback-resume.test.ts +197 -0
- package/telegram-plugin/tests/gateway-clean-shutdown-marker.test.ts +117 -0
- package/telegram-plugin/tests/gateway-no-reply-single-emit.test.ts +4 -11
- package/telegram-plugin/tests/history.test.ts +60 -0
- package/telegram-plugin/tests/model-command.test.ts +134 -0
- package/telegram-plugin/tests/model-unavailable.test.ts +118 -0
- package/telegram-plugin/tests/narrative-dedup.test.ts +118 -0
- package/telegram-plugin/tests/orphaned-reply-rearm.test.ts +285 -0
- package/telegram-plugin/tests/over-ping-final-answer-decoupling.test.ts +194 -0
- package/telegram-plugin/tests/over-ping-safety-net.test.ts +2 -2
- package/telegram-plugin/tests/per-topic-current-turn.test.ts +373 -0
- package/telegram-plugin/tests/permission-card-origin-kill-switch.test.ts +42 -0
- package/telegram-plugin/tests/permission-rule.test.ts +17 -0
- package/telegram-plugin/tests/permission-title.test.ts +206 -17
- package/telegram-plugin/tests/quota-watch.test.ts +252 -9
- package/telegram-plugin/tests/reply-terminal-reaction.test.ts +6 -1
- package/telegram-plugin/tests/repo-context-pretool.test.ts +62 -0
- package/telegram-plugin/tests/represent-guard.test.ts +162 -0
- package/telegram-plugin/tests/session-tail.test.ts +147 -3
- package/telegram-plugin/tests/silence-liveness-wiring.test.ts +18 -0
- package/telegram-plugin/tests/status-card-budget-parity.test.ts +72 -0
- package/telegram-plugin/tests/status-surface-log.test.ts +146 -0
- package/telegram-plugin/tests/subagent-watcher-clip-narrative.test.ts +58 -0
- package/telegram-plugin/tests/subagent-watcher-parent-turn-key.test.ts +102 -0
- package/telegram-plugin/tests/subagent-watcher-workflow-visibility.test.ts +225 -0
- package/telegram-plugin/tests/subagent-watcher.test.ts +147 -0
- package/telegram-plugin/tests/telegram-activity-visibility-integration.test.ts +597 -0
- package/telegram-plugin/tests/telegram-format.test.ts +101 -6
- package/telegram-plugin/tests/tool-activity-summary.test.ts +550 -15
- package/telegram-plugin/tests/tool-label-pretool.test.ts +73 -0
- package/telegram-plugin/tests/tool-label-sidecar.test.ts +44 -0
- package/telegram-plugin/tests/tool-labels.test.ts +67 -0
- package/telegram-plugin/tests/turn-liveness-floor.test.ts +196 -0
- package/telegram-plugin/tests/turn-liveness-invariant.test.ts +340 -0
- package/telegram-plugin/tests/welcome-text.test.ts +32 -3
- package/telegram-plugin/tests/worker-activity-feed.test.ts +470 -22
- package/telegram-plugin/tool-activity-summary.ts +375 -58
- package/telegram-plugin/turn-liveness-floor.ts +240 -0
- package/telegram-plugin/uat/assertions.ts +115 -0
- package/telegram-plugin/uat/driver.ts +68 -0
- package/telegram-plugin/uat/scenarios/bg-sub-agent-dispatch-dm.test.ts +119 -133
- package/telegram-plugin/uat/scenarios/jtbd-answer-pings.test.ts +94 -0
- package/telegram-plugin/uat/scenarios/jtbd-cross-turn-card-dm.test.ts +109 -0
- package/telegram-plugin/uat/scenarios/jtbd-foreground-feed-thinkgap-dm.test.ts +478 -0
- package/telegram-plugin/uat/scenarios/jtbd-foreground-feed-visibility-dm.test.ts +396 -0
- package/telegram-plugin/uat/scenarios/jtbd-liveness-feed-open-dm.test.ts +202 -0
- package/telegram-plugin/uat/scenarios/jtbd-reply-is-last-dm.test.ts +202 -0
- package/telegram-plugin/uat/scenarios/reactions-dm.test.ts +93 -87
- package/telegram-plugin/welcome-text.ts +13 -1
- package/telegram-plugin/worker-activity-feed.ts +157 -82
- package/telegram-plugin/draft-transport.ts +0 -122
- package/telegram-plugin/tests/draft-retirement-wiring.test.ts +0 -82
- package/telegram-plugin/tests/draft-transport.test.ts +0 -211
|
@@ -11150,7 +11150,7 @@ var TelegramChannelSchema = exports_external.object({
|
|
|
11150
11150
|
format: exports_external.enum(["html", "markdownv2", "text"]).optional().describe("Default reply format passed to the plugin"),
|
|
11151
11151
|
rate_limit_ms: exports_external.number().optional().describe("Minimum delay between outgoing messages in ms"),
|
|
11152
11152
|
stream_mode: exports_external.enum(["pty", "checklist"]).optional().describe("How live progress is streamed to Telegram during a turn. " + "'pty' (default) surfaces text snapshots of Claude Code's TUI — " + "compatible but can flicker as Ink re-renders. 'checklist' drives " + "a structured progress card from session-tail events — stable " + "order, per-tool status emojis, fires only on semantic transitions."),
|
|
11153
|
-
stream_throttle_ms: exports_external.number().int().nonnegative().optional().describe("Throttle window in ms between successive stream edits
|
|
11153
|
+
stream_throttle_ms: exports_external.number().int().nonnegative().optional().describe("Throttle window in ms between successive in-place stream edits " + "during a turn. Lower = more responsive stream, higher = fewer API " + "calls. Floored at 250 by draft-stream itself. Default 400 ms for DMs " + "and 1000 ms for groups/forums (respects Telegram's ~1 edit/sec/message " + "practical ceiling). Override per-agent if a particular agent needs " + "snappier or quieter streaming."),
|
|
11154
11154
|
clear_status_on_completion: exports_external.boolean().optional().describe("When true, the live activity/status feed (the in-place 'what it's " + "doing' message — Reading X, Searching the web for Y, …) is DELETED " + "when the turn's final answer lands, so only the reply remains. " + "Default false: the status message is left in the chat as a record " + "(its last step marked done) — no post-then-delete. Per-agent " + "override; cascades defaults → profile → agent (per-key)."),
|
|
11155
11155
|
hotReloadStable: exports_external.boolean().optional().describe("If true, the stable workspace prefix (AGENTS.md, SOUL.md, USER.md, " + "IDENTITY.md, TOOLS.md) is re-injected on every turn via " + "the UserPromptSubmit hook instead of baked into --append-system-prompt " + "at session start. Lets workspace edits propagate without a restart. " + "Costs ~5-10% per-turn latency/spend since the stable prefix is no " + "longer prompt-cached."),
|
|
11156
11156
|
inject_on_change: exports_external.boolean().optional().describe("Context-efficiency gate for per-turn hook injection (default true). " + "When true (the default), the turn-pacing directive and dynamic " + "workspace content are only re-emitted when their content changes or " + "the session_id changes — suppressing redundant injection that " + "otherwise triples compaction frequency. Set to false to revert to " + "the legacy always-emit behaviour (every turn injects the full " + "content regardless of whether it changed)."),
|
|
@@ -11238,6 +11238,14 @@ var GoogleWorkspaceConfigSchema = exports_external.object({
|
|
|
11238
11238
|
approvers: exports_external.array(ApproverIdSchema).min(1).describe("Array of numeric Telegram user IDs authorized to approve drive onboarding. " + "At least one must be specified."),
|
|
11239
11239
|
tier: GoogleWorkspaceTierSchema.optional().describe("RFC G Phase 1: which upstream MCP tier to expose. " + "core (default) = ~16 tools (Drive+Docs+Sheets+Calendar). " + "extended = ~40 tools (+Slides, Forms, Tasks, Chat). " + "complete = ~60+ tools (+Gmail; not recommended yet — see RFC G §5).")
|
|
11240
11240
|
}).optional();
|
|
11241
|
+
var LiteLLMConfigSchema = exports_external.object({
|
|
11242
|
+
enabled: exports_external.boolean().optional().describe("Opt-in toggle. When true, `switchroom apply` provisions a per-agent " + "LiteLLM virtual key and injects routing env into the container. " + "Default OFF."),
|
|
11243
|
+
base_url: exports_external.string().optional().describe("LiteLLM proxy base URL the agent's claude CLI routes through, e.g. " + "'http://127.0.0.1:4010'. Agents use network_mode:host, so loopback " + "reaches a host-bound proxy. Exported as ANTHROPIC_BASE_URL."),
|
|
11244
|
+
admin_key: exports_external.string().optional().describe("LiteLLM master/admin key used at apply time to provision the team + " + "virtual key. Supports a vault reference (e.g. " + "'vault:litellm/master-key') — resolution happens at apply time via " + "the vault-broker. Never injected into the agent container."),
|
|
11245
|
+
team: exports_external.string().optional().describe("LiteLLM team alias the per-agent key is created under. Defaults to " + "'switchroom' (applied in code, not as a schema default)."),
|
|
11246
|
+
small_fast_model: exports_external.string().optional().describe("Model id exported as ANTHROPIC_SMALL_FAST_MODEL for the claude CLI's " + "background/fast lane, e.g. 'claude-haiku-4-5-20251001'."),
|
|
11247
|
+
tags: exports_external.record(exports_external.string(), exports_external.string()).optional().describe("Extra key/value metadata tags attached to the provisioned LiteLLM " + "virtual key. Merged per-key across cascade layers (agent wins).")
|
|
11248
|
+
}).optional().describe("LiteLLM routing config — opt-in per-agent virtual-key auto-provisioning " + "+ routing env. Default OFF. See LiteLLMConfigSchema doc for the full flow.");
|
|
11241
11249
|
var MicrosoftWorkspaceConfigSchema = exports_external.object({
|
|
11242
11250
|
microsoft_client_id: exports_external.string().min(1).optional().describe("Microsoft OAuth application (client) ID from Entra portal " + "(literal string or vault reference e.g. " + "'vault:microsoft-oauth-client-id'). OPTIONAL — omit it to use " + "switchroom's shipped default Microsoft app (zero-config). " + "Set it only to bring your own Entra app (BYO)."),
|
|
11243
11251
|
microsoft_client_secret: exports_external.string().min(1).optional().describe("Microsoft OAuth client secret. Optional — public-client apps " + "(Mobile + Desktop platform with 'Allow public client flows' " + "enabled) work without a secret; confidential clients pass " + "one. Either literal or vault reference e.g. " + "'vault:microsoft-oauth-client-secret'."),
|
|
@@ -11334,6 +11342,7 @@ var profileFields = {
|
|
|
11334
11342
|
mcp_servers: exports_external.record(exports_external.string(), exports_external.unknown()).optional(),
|
|
11335
11343
|
hooks: AgentHooksSchema,
|
|
11336
11344
|
env: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
11345
|
+
litellm: LiteLLMConfigSchema,
|
|
11337
11346
|
system_prompt_append: exports_external.string().optional(),
|
|
11338
11347
|
skills: exports_external.array(exports_external.string()).optional(),
|
|
11339
11348
|
bundled_skills: exports_external.record(exports_external.string(), exports_external.boolean()).optional().describe("Opt-out map for switchroom's bundled-default skills " + "(e.g. skill-creator, mcp-builder, webapp-testing, pdf, docx, " + "xlsx, pptx, switchroom-cli, switchroom-status, switchroom-health). " + "Set a key to `false` to suppress that default for this agent. " + "Cascades from defaults.bundled_skills."),
|
|
@@ -11406,6 +11415,7 @@ var AgentSchema = exports_external.object({
|
|
|
11406
11415
|
mcp_servers: exports_external.record(exports_external.string(), exports_external.unknown()).optional().describe("Additional MCP server configurations"),
|
|
11407
11416
|
hooks: AgentHooksSchema.describe("Claude Code lifecycle hooks (SessionStart, UserPromptSubmit, Stop, etc). " + "Written to settings.json.hooks in Claude Code's native shape."),
|
|
11408
11417
|
env: exports_external.record(exports_external.string(), exports_external.string()).optional().describe("Environment variables exported in start.sh before claude runs"),
|
|
11418
|
+
litellm: LiteLLMConfigSchema.describe("Per-agent LiteLLM routing override. Presence with `enabled: true` opts " + "this agent IN to per-agent virtual-key auto-provisioning + routing env " + "(falls back to the top-level `litellm:` block for base_url/admin_key/" + "team/small_fast_model). Deep-merges one level over defaults/profile; " + "`tags` merge per-key, agent wins. Default OFF."),
|
|
11409
11419
|
system_prompt_append: exports_external.string().optional().describe("Text passed via claude's --append-system-prompt flag. " + "Appended to the default or CLAUDE.md-derived system prompt."),
|
|
11410
11420
|
skills: exports_external.array(exports_external.string()).optional().describe("Names of skills from switchroom.skills_dir to symlink into this " + "agent's skills/ directory. Unioned with defaults.skills."),
|
|
11411
11421
|
bundled_skills: exports_external.record(exports_external.string(), exports_external.boolean()).optional().describe("Per-agent override of switchroom's bundled-default skills " + "(skill-creator, mcp-builder, webapp-testing, pdf, docx, xlsx, " + "pptx, switchroom-cli/status/health). Set a key to `false` to " + "opt out for this agent. Per-agent value wins over defaults.bundled_skills."),
|
|
@@ -11531,7 +11541,7 @@ var WebServiceConfigSchema = exports_external.object({
|
|
|
11531
11541
|
});
|
|
11532
11542
|
var HostdConfigSchema = exports_external.object({
|
|
11533
11543
|
config_edit_enabled: exports_external.boolean().default(false).describe("Opt-in toggle for the `config_propose_edit` hostd verb (RFC " + "admin-agent-config-edit §3). Default false — the verb returns " + "`E_CONFIG_EDIT_DISABLED` until the operator explicitly flips " + "this to true. When true, admin agents can propose unified-diff " + "patches against " + "`/state/config/switchroom.yaml`, gated by an operator approval " + "card in the primary chat. Same trust posture as `update_apply` " + "and `agent_restart`: the human-in-the-loop tap is the security " + "boundary, not the agent's judgement."),
|
|
11534
|
-
config_edit_rate_per_hour: exports_external.number().int().min(1).max(20).default(3).describe("Per-requesting-agent rate cap for `config_propose_edit` cards " + "(RFC admin-agent-config-edit §5). Default 3 cards/hour; min 1, " + "max 20.
|
|
11544
|
+
config_edit_rate_per_hour: exports_external.number().int().min(1).max(20).default(3).describe("Per-requesting-agent rate cap for `config_propose_edit` cards " + "(RFC admin-agent-config-edit §5). Default 3 cards/hour; min 1, " + "max 20. ENFORCED server-side: a caller exceeding this in a sliding " + "1-hour window is rejected with `E_RATE_LIMITED` (carrying a " + "`retry_after` fix) instead of posting another operator approval " + "card — so a looping agent is throttled rather than spamming the chat.")
|
|
11535
11545
|
});
|
|
11536
11546
|
var CronEgressSchema = exports_external.object({
|
|
11537
11547
|
allowed_hosts: exports_external.array(exports_external.string().min(1)).default([]).describe("Hosts a poll may reach (exact, https-only). loopback/private/IP-literal are always rejected."),
|
|
@@ -11564,11 +11574,14 @@ var SwitchroomConfigSchema = exports_external.object({
|
|
|
11564
11574
|
message: "Consumer name must be a path-safe slug (letters, digits, underscore, hyphen)"
|
|
11565
11575
|
}).describe("Socket-path identity; binds at /run/switchroom/auth-broker/<name>/sock"),
|
|
11566
11576
|
account: exports_external.string().min(1).describe("Pinned account label for this consumer. `get-credentials` returns " + "this account's credentials; `mark-exhausted` from this consumer " + "only affects this account."),
|
|
11567
|
-
uid: exports_external.number().int().nonnegative().optional().describe("Optional UID to chown the consumer socket to (defaults to 0 = root, " + "suitable for sibling containers running as root).")
|
|
11568
|
-
|
|
11577
|
+
uid: exports_external.number().int().nonnegative().optional().describe("Optional UID to chown the consumer socket to (defaults to 0 = root, " + "suitable for sibling containers running as root)."),
|
|
11578
|
+
mirror_dir: exports_external.string().optional().describe("Optional host-side directory path. When set, the broker actively " + "writes the consumer's effective-account `.credentials.json` mirror " + "here — in addition to serving creds on demand via `get-credentials`. " + "Use this to eliminate the pull-latency gap: without a mirror the " + "consumer only gets failover creds at its next scheduled re-fetch " + "(up to 30 min). With a mirror the broker pushes failover creds " + "immediately when it detects exhaustion (consumer-quota-sensor tick, " + "or a mark-exhausted RPC on the pinned account). The directory must " + "be accessible to the broker container (bind-mounted from the host) " + "and to the consumer container; the broker writes " + "`<mirror_dir>/.credentials.json` atomically. Chown is attempted to " + "`uid` (default 0) — swallowed when CAP_CHOWN is absent.")
|
|
11579
|
+
})).optional().describe("Non-agent peers that hold a broker socket (RFC H §4.8). Each gets " + "its own `/run/switchroom/auth-broker/<name>/sock` chowned to its UID. " + "Consumers cannot be admins; a consumer name that collides with an " + "agent (whether that agent has `admin: true` or not) is a config " + "error caught at schema validation."),
|
|
11580
|
+
allow_overage_accounts: exports_external.array(exports_external.string().min(1)).optional().describe("Opt-in list of account labels (bare strings matching `auth.active` / " + "`auth.fallback_order` entries) that may be served PAST the weekly " + "utilization wall when Anthropic overage billing is available for the " + "account (`overageStatus === 'allowed'`). Overage is REAL MONEY — " + "default is empty (no account gets this). An account in this list is " + "only kept eligible when its fresh quota snapshot reports " + "`overageStatus: 'allowed'` AND `overageDisabledReason` is NOT " + "'out_of_credits' (i.e. the overage credit has not been exhausted). " + "As soon as `overageDisabledReason` becomes 'out_of_credits', the " + "account is blocked immediately regardless of this flag. Overage lifts " + "ONLY the utilization wall — it cannot lift an active exhaustion mark " + "written by a real 429 (`mark-exhausted`).")
|
|
11569
11581
|
}).optional().describe("Switchroom-auth-broker configuration (RFC H). Fleet-wide active account, " + "fallback order, admin-agent ACL, and ephemeral-consumer surface. " + "Required from the v0.8+ schema onwards; pre-v0.8 fleets are migrated " + "in-place by `switchroom apply` (see src/auth/migrate-schema.ts)."),
|
|
11570
11582
|
drive: GoogleWorkspaceConfigSchema.describe("RFC D legacy key — use `google_workspace:` instead. Optional Google " + "Workspace onboarding configuration. When set, supplies Google OAuth " + "client credentials, the approver allowlist for `switchroom drive " + "connect`, and the optional tier knob. Env vars " + "(SWITCHROOM_GOOGLE_CLIENT_ID, SWITCHROOM_GOOGLE_CLIENT_SECRET, " + "SWITCHROOM_APPROVER_USER_ID) take precedence over this block when " + "set, preserving back-compat with the env-only flow shipped in #766."),
|
|
11571
11583
|
google_workspace: GoogleWorkspaceConfigSchema.describe("RFC G canonical key. Top-level Google Workspace configuration — " + "OAuth client credentials, approver allowlist, and tier knob (`core` " + "| `extended` | `complete`, default `core`). Mutually exclusive with " + "`drive:` at the top level (loader fails fast if both are set)."),
|
|
11584
|
+
litellm: LiteLLMConfigSchema.describe("Top-level LiteLLM routing infra — global base_url, admin_key (the " + "LiteLLM master key, supports a `vault:` ref), team alias, and " + "small_fast_model shared by every agent that opts in. Set `enabled: " + "true` here to default the whole fleet on (each agent can still set " + "`litellm.enabled: false` to opt out). Default OFF."),
|
|
11572
11585
|
microsoft_workspace: MicrosoftWorkspaceConfigSchema.describe("RFC #1873 (Microsoft 365 integration). Top-level Microsoft Workspace " + "configuration — OAuth client credentials (Entra app), authority " + "endpoint (defaults to /common for personal MSA + work), and the " + "org_mode opt-in for Teams/SharePoint surfaces. Block is optional; " + "when omitted the broker does not register the Microsoft provider."),
|
|
11573
11586
|
notion_workspace: NotionWorkspaceConfigSchema.describe("RFC reference/rfcs/notion-integration.md. Top-level Notion integration " + "config — vault key for the integration token, friendly-name → " + "database UUID map, optional MCP-package version pin, and optional " + "global rate-limit override (default 3 rps, Notion's documented " + "public-API limit). Block is optional; when omitted no agent gets a " + "Notion MCP entry regardless of per-agent config."),
|
|
11574
11587
|
quota: QuotaConfigSchema.optional().describe("Optional weekly/monthly USD spend budgets rendered in the session " + "greeting. Usage is read from ccusage at runtime; no network calls."),
|
|
@@ -11988,6 +12001,24 @@ function mergeAgentConfig(defaultsIn, agentIn) {
|
|
|
11988
12001
|
...merged.env ?? {}
|
|
11989
12002
|
};
|
|
11990
12003
|
}
|
|
12004
|
+
if (defaults.litellm || merged.litellm) {
|
|
12005
|
+
const base = defaults.litellm ?? {};
|
|
12006
|
+
const override = merged.litellm ?? {};
|
|
12007
|
+
const combined = { ...base };
|
|
12008
|
+
for (const [k, v] of Object.entries(override)) {
|
|
12009
|
+
if (v === undefined)
|
|
12010
|
+
continue;
|
|
12011
|
+
if (k === "tags" && base.tags && typeof v === "object" && v !== null && !Array.isArray(v)) {
|
|
12012
|
+
combined.tags = {
|
|
12013
|
+
...base.tags,
|
|
12014
|
+
...v
|
|
12015
|
+
};
|
|
12016
|
+
} else {
|
|
12017
|
+
combined[k] = v;
|
|
12018
|
+
}
|
|
12019
|
+
}
|
|
12020
|
+
merged.litellm = combined;
|
|
12021
|
+
}
|
|
11991
12022
|
if (defaults.subagents || merged.subagents) {
|
|
11992
12023
|
const dSub = defaults.subagents ?? {};
|
|
11993
12024
|
const mSub = merged.subagents ?? {};
|
|
@@ -13625,7 +13656,8 @@ var ProbeQuotaRequestSchema = exports_external.object({
|
|
|
13625
13656
|
op: exports_external.literal("probe-quota"),
|
|
13626
13657
|
id: exports_external.string().min(1),
|
|
13627
13658
|
accounts: exports_external.array(exports_external.string().min(1)).min(1).max(32),
|
|
13628
|
-
timeoutMs: exports_external.number().int().positive().max(60000).optional()
|
|
13659
|
+
timeoutMs: exports_external.number().int().positive().max(60000).optional(),
|
|
13660
|
+
forceLive: exports_external.boolean().optional()
|
|
13629
13661
|
});
|
|
13630
13662
|
var ClaimNotificationRequestSchema = exports_external.object({
|
|
13631
13663
|
v: exports_external.literal(PROTOCOL_VERSION),
|
|
@@ -13676,7 +13708,8 @@ var ListStateDataSchema = exports_external.object({
|
|
|
13676
13708
|
fallback_order: exports_external.array(exports_external.string()),
|
|
13677
13709
|
accounts: exports_external.array(AccountStateSchema),
|
|
13678
13710
|
agents: exports_external.array(AgentStateSchema),
|
|
13679
|
-
consumers: exports_external.array(ConsumerStateSchema)
|
|
13711
|
+
consumers: exports_external.array(ConsumerStateSchema),
|
|
13712
|
+
active_overage_serving: exports_external.boolean().optional()
|
|
13680
13713
|
});
|
|
13681
13714
|
var SetActiveDataSchema = exports_external.object({
|
|
13682
13715
|
active: exports_external.string(),
|
|
@@ -13880,13 +13913,14 @@ class AuthBrokerClient {
|
|
|
13880
13913
|
});
|
|
13881
13914
|
return data;
|
|
13882
13915
|
}
|
|
13883
|
-
async probeQuota(accounts, timeoutMs) {
|
|
13916
|
+
async probeQuota(accounts, timeoutMs, forceLive) {
|
|
13884
13917
|
const data = await this.send({
|
|
13885
13918
|
v: PROTOCOL_VERSION,
|
|
13886
13919
|
id: randomUUID(),
|
|
13887
13920
|
op: "probe-quota",
|
|
13888
13921
|
accounts: [...accounts],
|
|
13889
|
-
...timeoutMs !== undefined ? { timeoutMs } : {}
|
|
13922
|
+
...timeoutMs !== undefined ? { timeoutMs } : {},
|
|
13923
|
+
...forceLive ? { forceLive: true } : {}
|
|
13890
13924
|
});
|
|
13891
13925
|
const parsed = data;
|
|
13892
13926
|
for (const entry of parsed.results) {
|
|
@@ -14568,7 +14602,8 @@ function recoverPendingEscalations(opts) {
|
|
|
14568
14602
|
startedAt,
|
|
14569
14603
|
finishedAt: opts.now(),
|
|
14570
14604
|
tier: esc.tier === "cheap" ? "cheap" : "main",
|
|
14571
|
-
...esc.cronModel ? { modelUsed: esc.cronModel } : {}
|
|
14605
|
+
...esc.cronModel ? { modelUsed: esc.cronModel } : {},
|
|
14606
|
+
...entry.name ? { scheduleName: entry.name } : {}
|
|
14572
14607
|
});
|
|
14573
14608
|
} catch (e) {
|
|
14574
14609
|
opts.log(`pending-escalation recovery failed for '${entry.poll.state_key}': ${e.message}`);
|
|
@@ -14612,7 +14647,8 @@ function registerAgentSchedule(opts) {
|
|
|
14612
14647
|
exitCode: -2,
|
|
14613
14648
|
outputSummary: summary2,
|
|
14614
14649
|
startedAt,
|
|
14615
|
-
finishedAt: now()
|
|
14650
|
+
finishedAt: now(),
|
|
14651
|
+
...entry.name ? { scheduleName: entry.name } : {}
|
|
14616
14652
|
});
|
|
14617
14653
|
if (more) {
|
|
14618
14654
|
let handle;
|
|
@@ -14638,7 +14674,8 @@ function registerAgentSchedule(opts) {
|
|
|
14638
14674
|
startedAt,
|
|
14639
14675
|
finishedAt: now(),
|
|
14640
14676
|
tier: fields.tier,
|
|
14641
|
-
...fields.modelUsed ? { modelUsed: fields.modelUsed } : {}
|
|
14677
|
+
...fields.modelUsed ? { modelUsed: fields.modelUsed } : {},
|
|
14678
|
+
...entry.name ? { scheduleName: entry.name } : {}
|
|
14642
14679
|
});
|
|
14643
14680
|
if (routing.tier === "poll" && opts.cheapCron && entry.poll) {
|
|
14644
14681
|
const stateKey = entry.poll.state_key;
|
|
@@ -14886,7 +14923,8 @@ async function main() {
|
|
|
14886
14923
|
outputSummary: "action replay skipped — runs on next tick (never double-fired)",
|
|
14887
14924
|
startedAt,
|
|
14888
14925
|
finishedAt: Date.now(),
|
|
14889
|
-
tier: "action"
|
|
14926
|
+
tier: "action",
|
|
14927
|
+
...m.entry.name ? { scheduleName: m.entry.name } : {}
|
|
14890
14928
|
});
|
|
14891
14929
|
continue;
|
|
14892
14930
|
}
|
|
@@ -14899,7 +14937,8 @@ async function main() {
|
|
|
14899
14937
|
outputSummary: "poll replay skipped — re-polls on next tick (stateful cursor)",
|
|
14900
14938
|
startedAt,
|
|
14901
14939
|
finishedAt: Date.now(),
|
|
14902
|
-
tier: "poll"
|
|
14940
|
+
tier: "poll",
|
|
14941
|
+
...m.entry.name ? { scheduleName: m.entry.name } : {}
|
|
14903
14942
|
});
|
|
14904
14943
|
continue;
|
|
14905
14944
|
}
|
|
@@ -14912,7 +14951,8 @@ async function main() {
|
|
|
14912
14951
|
exitCode: result.delivered ? 0 : -1,
|
|
14913
14952
|
outputSummary: result.delivered ? `replayed (originally scheduled at ${new Date(m.expectedFireMs).toISOString()})` : "replay attempted but gateway not connected",
|
|
14914
14953
|
startedAt,
|
|
14915
|
-
finishedAt: Date.now()
|
|
14954
|
+
finishedAt: Date.now(),
|
|
14955
|
+
...m.entry.name ? { scheduleName: m.entry.name } : {}
|
|
14916
14956
|
});
|
|
14917
14957
|
}
|
|
14918
14958
|
}
|
|
@@ -14957,7 +14997,8 @@ Briefly and plainly tell the user these scheduled runs did not ` + "happen so th
|
|
|
14957
14997
|
exitCode: 0,
|
|
14958
14998
|
outputSummary: `skip-notice: run at ${new Date(s.expectedFireMs).toISOString()} ` + `was older than the ${windowMinutes}min replay window and was ` + "not executed",
|
|
14959
14999
|
startedAt: s.expectedFireMs,
|
|
14960
|
-
finishedAt: s.expectedFireMs
|
|
15000
|
+
finishedAt: s.expectedFireMs,
|
|
15001
|
+
...s.entry.name ? { scheduleName: s.entry.name } : {}
|
|
14961
15002
|
});
|
|
14962
15003
|
}
|
|
14963
15004
|
}
|