fix: clarify auth order exclusions
This commit is contained in:
@@ -25,6 +25,8 @@ Docs: https://docs.clawd.bot
|
||||
- CLI: render auth probe results as a table in `clawdbot models status`.
|
||||
- CLI: suppress probe-only embedded logs unless `--verbose` is set.
|
||||
- CLI: move auth probe errors below the table to reduce wrapping.
|
||||
- CLI: prevent ANSI color bleed when table cells wrap.
|
||||
- CLI: explain when auth profiles are excluded by auth.order in probe details.
|
||||
- Linux: include env-configured user bin roots in systemd PATH and align PATH audits. (#1512) Thanks @robbyczgw-cla.
|
||||
- TUI: render Gateway slash-command replies as system output (for example, `/context`).
|
||||
- Media: preserve PNG alpha when possible; fall back to JPEG when still over size cap. (#1491) Thanks @robbyczgw-cla.
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
ensureAuthProfileStore,
|
||||
listProfilesForProvider,
|
||||
resolveAuthProfileDisplayLabel,
|
||||
resolveAuthProfileOrder,
|
||||
} from "../../agents/auth-profiles.js";
|
||||
import { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
|
||||
import { describeFailoverError } from "../../agents/failover-error.js";
|
||||
@@ -143,6 +144,25 @@ function buildProbeTargets(params: {
|
||||
});
|
||||
|
||||
const profileIds = listProfilesForProvider(store, providerKey);
|
||||
const explicitOrder = (() => {
|
||||
const order = store.order;
|
||||
if (order) {
|
||||
for (const [key, value] of Object.entries(order)) {
|
||||
if (normalizeProviderId(key) === providerKey) return value;
|
||||
}
|
||||
}
|
||||
const cfgOrder = cfg?.auth?.order;
|
||||
if (cfgOrder) {
|
||||
for (const [key, value] of Object.entries(cfgOrder)) {
|
||||
if (normalizeProviderId(key) === providerKey) return value;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
})();
|
||||
const allowedProfiles =
|
||||
explicitOrder && explicitOrder.length > 0
|
||||
? new Set(resolveAuthProfileOrder({ cfg, store, provider: providerKey }))
|
||||
: null;
|
||||
const filteredProfiles = profileFilter.size
|
||||
? profileIds.filter((id) => profileFilter.has(id))
|
||||
: profileIds;
|
||||
@@ -152,6 +172,32 @@ function buildProbeTargets(params: {
|
||||
const profile = store.profiles[profileId];
|
||||
const mode = profile?.type;
|
||||
const label = resolveAuthProfileDisplayLabel({ cfg, store, profileId });
|
||||
if (explicitOrder && !explicitOrder.includes(profileId)) {
|
||||
results.push({
|
||||
provider: providerKey,
|
||||
model: model ? `${model.provider}/${model.model}` : undefined,
|
||||
profileId,
|
||||
label,
|
||||
source: "profile",
|
||||
mode,
|
||||
status: "unknown",
|
||||
error: "Excluded by auth.order for this provider.",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
if (allowedProfiles && !allowedProfiles.has(profileId)) {
|
||||
results.push({
|
||||
provider: providerKey,
|
||||
model: model ? `${model.provider}/${model.model}` : undefined,
|
||||
profileId,
|
||||
label,
|
||||
source: "profile",
|
||||
mode,
|
||||
status: "unknown",
|
||||
error: "Auth profile credentials are missing or expired.",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
if (!model) {
|
||||
results.push({
|
||||
provider: providerKey,
|
||||
|
||||
@@ -85,6 +85,31 @@ describe("renderTable", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("resets ANSI styling on wrapped lines", () => {
|
||||
const reset = "\x1b[0m";
|
||||
const out = renderTable({
|
||||
width: 24,
|
||||
columns: [
|
||||
{ key: "K", header: "K", minWidth: 3 },
|
||||
{ key: "V", header: "V", flex: true, minWidth: 10 },
|
||||
],
|
||||
rows: [
|
||||
{
|
||||
K: "X",
|
||||
V: `\x1b[31m${"a".repeat(80)}${reset}`,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const lines = out.split("\n").filter((line) => line.includes("a"));
|
||||
for (const line of lines) {
|
||||
const resetIndex = line.lastIndexOf(reset);
|
||||
const lastSep = line.lastIndexOf("│");
|
||||
expect(resetIndex).toBeGreaterThan(-1);
|
||||
expect(lastSep).toBeGreaterThan(resetIndex);
|
||||
}
|
||||
});
|
||||
|
||||
it("respects explicit newlines in cell values", () => {
|
||||
const out = renderTable({
|
||||
width: 48,
|
||||
|
||||
@@ -91,6 +91,27 @@ function wrapLine(text: string, width: number): string[] {
|
||||
i += ch.length;
|
||||
}
|
||||
|
||||
const firstCharIndex = tokens.findIndex((t) => t.kind === "char");
|
||||
if (firstCharIndex < 0) return [text];
|
||||
let lastCharIndex = -1;
|
||||
for (let i = tokens.length - 1; i >= 0; i -= 1) {
|
||||
if (tokens[i]?.kind === "char") {
|
||||
lastCharIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const prefixAnsi = tokens
|
||||
.slice(0, firstCharIndex)
|
||||
.filter((t) => t.kind === "ansi")
|
||||
.map((t) => t.value)
|
||||
.join("");
|
||||
const suffixAnsi = tokens
|
||||
.slice(lastCharIndex + 1)
|
||||
.filter((t) => t.kind === "ansi")
|
||||
.map((t) => t.value)
|
||||
.join("");
|
||||
const coreTokens = tokens.slice(firstCharIndex, lastCharIndex + 1);
|
||||
|
||||
const lines: string[] = [];
|
||||
const isBreakChar = (ch: string) =>
|
||||
ch === " " || ch === "\t" || ch === "/" || ch === "-" || ch === "_" || ch === ".";
|
||||
@@ -136,7 +157,7 @@ function wrapLine(text: string, width: number): string[] {
|
||||
lastBreakIndex = null;
|
||||
};
|
||||
|
||||
for (const token of tokens) {
|
||||
for (const token of coreTokens) {
|
||||
if (token.kind === "ansi") {
|
||||
buf.push(token);
|
||||
continue;
|
||||
@@ -162,7 +183,12 @@ function wrapLine(text: string, width: number): string[] {
|
||||
}
|
||||
|
||||
flushAt(buf.length);
|
||||
return lines.length ? lines : [""];
|
||||
if (!lines.length) return [""];
|
||||
if (!prefixAnsi && !suffixAnsi) return lines;
|
||||
return lines.map((line) => {
|
||||
if (!line) return line;
|
||||
return `${prefixAnsi}${line}${suffixAnsi}`;
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeWidth(n: number | undefined): number | undefined {
|
||||
|
||||
Reference in New Issue
Block a user