fix: trim /status oauth output
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
- Tools: add Firecrawl fallback for `web_fetch` when configured.
|
||||
- Tools: send Chrome-like headers by default for `web_fetch` to improve extraction on bot-sensitive sites.
|
||||
- Tools: Firecrawl fallback now uses bot-circumvention + cache by default; remove basic HTML fallback when extraction fails.
|
||||
- Status: trim `/status` to current-provider usage only and drop the OAuth/token block.
|
||||
- Directory: unify `clawdbot directory` across channels and plugin channels.
|
||||
- UI: allow deleting sessions from the Control UI.
|
||||
- Skills: add user-invocable skill commands and expanded skill command registration.
|
||||
|
||||
@@ -11,7 +11,7 @@ read_when:
|
||||
- No estimated costs; only the provider-reported windows.
|
||||
|
||||
## Where it shows up
|
||||
- `/status` in chats: emoji‑rich status card with session tokens + estimated cost (API key only). When OAuth/token profiles exist, the **OAuth/token status block** includes provider usage headers (when available).
|
||||
- `/status` in chats: emoji‑rich status card with session tokens + estimated cost (API key only). Provider usage shows for the **current model provider** when available.
|
||||
- `/cost on|off` in chats: toggles per‑response usage lines (OAuth shows tokens only).
|
||||
- CLI: `clawdbot status --usage` prints a full per-provider breakdown.
|
||||
- CLI: `clawdbot channels list` prints the same usage snapshot alongside provider config (use `--no-usage` to skip).
|
||||
|
||||
@@ -58,7 +58,7 @@ They run immediately, are stripped before the model sees the message, and the re
|
||||
Text + native (when enabled):
|
||||
- `/help`
|
||||
- `/commands`
|
||||
- `/status` (show current status; includes provider usage/quota when available, plus OAuth/token status block when OAuth profiles exist)
|
||||
- `/status` (show current status; includes provider usage/quota for the current model provider when available)
|
||||
- `/context [list|detail|json]` (explain “context”; `detail` shows per-file + per-tool + per-skill + system prompt size)
|
||||
- `/usage` (alias: `/status`)
|
||||
- `/whoami` (show your sender id; alias: `/id`)
|
||||
@@ -105,7 +105,7 @@ Notes:
|
||||
|
||||
## Usage vs cost (what shows where)
|
||||
|
||||
- **Provider usage/quota** (example: “Claude 80% left”) shows up in `/status` when provider usage tracking is enabled.
|
||||
- **Provider usage/quota** (example: “Claude 80% left”) shows up in `/status` for the current model provider when usage tracking is enabled.
|
||||
- **Per-response tokens/cost** is controlled by `/cost on|off` (appended to normal replies).
|
||||
- `/model status` is about **models/auth/endpoints**, not usage.
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
resolveAuthProfileDisplayLabel,
|
||||
resolveAuthProfileOrder,
|
||||
} from "../../agents/auth-profiles.js";
|
||||
import { buildAuthHealthSummary, formatRemainingShort } from "../../agents/auth-health.js";
|
||||
import { getCustomProviderApiKey, resolveEnvApiKey } from "../../agents/model-auth.js";
|
||||
import { normalizeProviderId } from "../../agents/model-selection.js";
|
||||
import type { ClawdbotConfig } from "../../config/config.js";
|
||||
@@ -16,10 +15,8 @@ import type { SessionEntry, SessionScope } from "../../config/sessions.js";
|
||||
import { logVerbose } from "../../globals.js";
|
||||
import {
|
||||
formatUsageSummaryLine,
|
||||
formatUsageWindowSummary,
|
||||
loadProviderUsageSummary,
|
||||
resolveUsageProviderId,
|
||||
type UsageProviderId,
|
||||
} from "../../infra/provider-usage.js";
|
||||
import { normalizeGroupActivation } from "../group-activation.js";
|
||||
import { buildStatusMessage } from "../status.js";
|
||||
@@ -134,17 +131,6 @@ export async function buildStatusReply(params: {
|
||||
? resolveSessionAgentId({ sessionKey, config: cfg })
|
||||
: resolveDefaultAgentId(cfg);
|
||||
const statusAgentDir = resolveAgentDir(cfg, statusAgentId);
|
||||
const authStore = ensureAuthProfileStore(statusAgentDir, { allowKeychainPrompt: false });
|
||||
const authHealth = buildAuthHealthSummary({ store: authStore, cfg });
|
||||
const oauthProfiles = authHealth.profiles.filter(
|
||||
(profile) => profile.type === "oauth" || profile.type === "token",
|
||||
);
|
||||
|
||||
const usageProviders = new Set<UsageProviderId>();
|
||||
for (const profile of oauthProfiles) {
|
||||
const entry = resolveUsageProviderId(profile.provider);
|
||||
if (entry) usageProviders.add(entry);
|
||||
}
|
||||
const currentUsageProvider = (() => {
|
||||
try {
|
||||
return resolveUsageProviderId(provider);
|
||||
@@ -152,47 +138,23 @@ export async function buildStatusReply(params: {
|
||||
return undefined;
|
||||
}
|
||||
})();
|
||||
if (usageProviders.size === 0 && currentUsageProvider) {
|
||||
usageProviders.add(currentUsageProvider);
|
||||
}
|
||||
const usageByProvider = new Map<string, string>();
|
||||
let usageSummaryCache: Awaited<ReturnType<typeof loadProviderUsageSummary>> | null | undefined;
|
||||
if (usageProviders.size > 0) {
|
||||
let usageLine: string | null = null;
|
||||
if (currentUsageProvider) {
|
||||
try {
|
||||
usageSummaryCache = await loadProviderUsageSummary({
|
||||
const usageSummary = await loadProviderUsageSummary({
|
||||
timeoutMs: 3500,
|
||||
providers: Array.from(usageProviders),
|
||||
providers: [currentUsageProvider],
|
||||
agentDir: statusAgentDir,
|
||||
});
|
||||
for (const snapshot of usageSummaryCache.providers) {
|
||||
const formatted = formatUsageWindowSummary(snapshot, {
|
||||
now: Date.now(),
|
||||
maxWindows: 2,
|
||||
includeResets: true,
|
||||
});
|
||||
if (formatted) usageByProvider.set(snapshot.provider, formatted);
|
||||
}
|
||||
const summaryLine = formatUsageSummaryLine(usageSummary, {
|
||||
now: Date.now(),
|
||||
maxProviders: 1,
|
||||
});
|
||||
if (summaryLine) usageLine = summaryLine;
|
||||
} catch {
|
||||
// ignore
|
||||
usageLine = null;
|
||||
}
|
||||
}
|
||||
|
||||
let usageLine: string | null = null;
|
||||
try {
|
||||
if (oauthProfiles.length === 0 && currentUsageProvider) {
|
||||
const summaryLine = usageSummaryCache
|
||||
? formatUsageSummaryLine(usageSummaryCache, { now: Date.now(), maxProviders: 1 })
|
||||
: null;
|
||||
if (summaryLine) {
|
||||
usageLine = summaryLine;
|
||||
} else {
|
||||
const usage = usageByProvider.get(currentUsageProvider);
|
||||
if (usage) usageLine = `📊 Usage: ${usage}`;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
usageLine = null;
|
||||
}
|
||||
const queueSettings = resolveQueueSettings({
|
||||
cfg,
|
||||
channel: command.channel,
|
||||
@@ -241,44 +203,5 @@ export async function buildStatusReply(params: {
|
||||
includeTranscriptUsage: false,
|
||||
});
|
||||
|
||||
const authStatusLines = (() => {
|
||||
if (oauthProfiles.length === 0) return [];
|
||||
const formatStatus = (status: string) => {
|
||||
if (status === "ok") return "ok";
|
||||
if (status === "static") return "static";
|
||||
if (status === "expiring") return "expiring";
|
||||
if (status === "missing") return "unknown";
|
||||
return "expired";
|
||||
};
|
||||
const profilesByProvider = new Map<string, typeof oauthProfiles>();
|
||||
for (const profile of oauthProfiles) {
|
||||
const current = profilesByProvider.get(profile.provider);
|
||||
if (current) current.push(profile);
|
||||
else profilesByProvider.set(profile.provider, [profile]);
|
||||
}
|
||||
const lines: string[] = ["OAuth/token status"];
|
||||
for (const [provider, profiles] of profilesByProvider) {
|
||||
const usageKey = resolveUsageProviderId(provider);
|
||||
const usage = usageKey ? usageByProvider.get(usageKey) : undefined;
|
||||
const usageSuffix = usage ? ` — usage: ${usage}` : "";
|
||||
lines.push(`- ${provider}${usageSuffix}`);
|
||||
for (const profile of profiles) {
|
||||
const labelText = profile.label || profile.profileId;
|
||||
const status = formatStatus(profile.status);
|
||||
const expiry =
|
||||
profile.status === "static"
|
||||
? ""
|
||||
: profile.expiresAt
|
||||
? ` expires in ${formatRemainingShort(profile.remainingMs)}`
|
||||
: " expires unknown";
|
||||
const source = profile.source !== "store" ? ` (${profile.source})` : "";
|
||||
lines.push(` - ${labelText} ${status}${expiry}${source}`);
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
})();
|
||||
|
||||
const fullStatusText =
|
||||
authStatusLines.length > 0 ? `${statusText}\n\n${authStatusLines.join("\n")}` : statusText;
|
||||
return { text: fullStatusText };
|
||||
return { text: statusText };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user