refactor(lint): reduce map spread patterns

This commit is contained in:
Peter Steinberger
2026-04-18 19:13:36 +01:00
parent cc919db83b
commit 1f1ff0567a
33 changed files with 391 additions and 328 deletions

View File

@@ -32,11 +32,10 @@ function createExtensionFallbackBrowserHarness(options?: {
const pages = (options?.urls ?? [undefined]).map(
(url) =>
({
on: pageOn,
context: () => context,
...(url ? { url: () => url } : {}),
}) as unknown as import("playwright-core").Page,
Object.assign(
{ on: pageOn, context: () => context },
url ? { url: () => url } : {},
) as unknown as import("playwright-core").Page,
);
(context as unknown as { pages: () => unknown[] }).pages = () => pages;

View File

@@ -106,11 +106,12 @@ export async function handleDiscordPresenceAction(
return jsonResult({
ok: true,
status,
activities: activities.map((a) => ({
type: a.type,
name: a.name,
...(a.url ? { url: a.url } : {}),
...(a.state ? { state: a.state } : {}),
})),
activities: activities.map((a) =>
Object.assign(
{ type: a.type, name: a.name },
a.url ? { url: a.url } : {},
a.state ? { state: a.state } : {},
),
),
});
}

View File

@@ -497,15 +497,17 @@ export async function executeExaWebSearchProviderTool(
typeof entry.publishedDate === "string" && entry.publishedDate
? entry.publishedDate
: undefined;
return {
title: title ? wrapWebContent(title, "web_search") : "",
url,
description: description ? wrapWebContent(description, "web_search") : "",
published,
siteName: resolveSiteName(url) || undefined,
...(summary ? { summary: wrapWebContent(summary, "web_search") } : {}),
...(highlightScores.length > 0 ? { highlightScores } : {}),
};
return Object.assign(
{
title: title ? wrapWebContent(title, `web_search`) : ``,
url,
description: description ? wrapWebContent(description, `web_search`) : ``,
published,
siteName: resolveSiteName(url) || undefined,
},
summary ? { summary: wrapWebContent(summary, `web_search`) } : {},
highlightScores.length > 0 ? { highlightScores } : {},
);
}),
};

View File

@@ -154,10 +154,12 @@ export async function sendGoogleChatMessage(params: {
body.thread = { name: thread };
}
if (attachments && attachments.length > 0) {
body.attachment = attachments.map((item) => ({
attachmentDataRef: { attachmentUploadToken: item.attachmentUploadToken },
...(item.contentName ? { contentName: item.contentName } : {}),
}));
body.attachment = attachments.map((item) =>
Object.assign(
{ attachmentDataRef: { attachmentUploadToken: item.attachmentUploadToken } },
item.contentName ? { contentName: item.contentName } : {},
),
);
}
const urlObj = new URL(`${CHAT_API_BASE}/${space}/messages`);
if (thread) {

View File

@@ -403,19 +403,21 @@ export async function listMemoryWikiImportInsights(
const updatedAt = sortedItems
.map((item) => item.updatedAt ?? item.createdAt)
.find((value): value is string => typeof value === "string" && value.length > 0);
return {
key,
label: sortedItems[0]?.topicLabel ?? humanizeLabelSuffix(key),
itemCount: sortedItems.length,
highRiskCount: sortedItems.filter((item) => item.riskLevel === "high").length,
withheldCount: sortedItems.filter((item) => item.digestStatus === "withheld").length,
preferenceSignalCount: sortedItems.reduce(
(sum, item) => sum + item.preferenceSignals.length,
0,
),
...(updatedAt ? { updatedAt } : {}),
items: sortedItems,
} satisfies MemoryWikiImportInsightCluster;
return Object.assign(
{
key,
label: sortedItems[0]?.topicLabel ?? humanizeLabelSuffix(key),
itemCount: sortedItems.length,
highRiskCount: sortedItems.filter((item) => item.riskLevel === `high`).length,
withheldCount: sortedItems.filter((item) => item.digestStatus === `withheld`).length,
preferenceSignalCount: sortedItems.reduce(
(sum, item) => sum + item.preferenceSignals.length,
0,
),
},
updatedAt ? { updatedAt } : {},
{ items: sortedItems },
) satisfies MemoryWikiImportInsightCluster;
})
.toSorted((left, right) => {
const leftKey = left.updatedAt ?? "";

View File

@@ -92,25 +92,23 @@ export async function listMemoryWikiPalace(
const items = pages
.map((page) => {
const parsed = parseWikiMarkdown(page.raw);
return {
pagePath: page.relativePath,
title: page.title,
kind: page.kind,
...(page.id ? { id: page.id } : {}),
...(normalizeTimestamp(page.updatedAt)
? { updatedAt: normalizeTimestamp(page.updatedAt) }
: {}),
...(typeof page.sourceType === "string" && page.sourceType.trim().length > 0
return Object.assign(
{ pagePath: page.relativePath, title: page.title, kind: page.kind },
page.id ? { id: page.id } : {},
normalizeTimestamp(page.updatedAt) ? { updatedAt: normalizeTimestamp(page.updatedAt) } : {},
typeof page.sourceType === `string` && page.sourceType.trim().length > 0
? { sourceType: page.sourceType.trim() }
: {}),
claimCount: page.claims.length,
questionCount: page.questions.length,
contradictionCount: page.contradictions.length,
claims: page.claims.map((claim) => claim.text).slice(0, 3),
questions: page.questions.slice(0, 3),
contradictions: page.contradictions.slice(0, 3),
...(extractSnippet(parsed.body) ? { snippet: extractSnippet(parsed.body) } : {}),
} satisfies MemoryWikiPalaceItem;
: {},
{
claimCount: page.claims.length,
questionCount: page.questions.length,
contradictionCount: page.contradictions.length,
claims: page.claims.map((claim) => claim.text).slice(0, 3),
questions: page.questions.slice(0, 3),
contradictions: page.contradictions.slice(0, 3),
},
extractSnippet(parsed.body) ? { snippet: extractSnippet(parsed.body) } : {},
) satisfies MemoryWikiPalaceItem;
})
.filter(
(item) =>
@@ -126,16 +124,18 @@ export async function listMemoryWikiPalace(
if (clusterItems.length === 0) {
return null;
}
return {
key: kind,
label: PALACE_KIND_LABELS[kind],
itemCount: clusterItems.length,
claimCount: clusterItems.reduce((sum, item) => sum + item.claimCount, 0),
questionCount: clusterItems.reduce((sum, item) => sum + item.questionCount, 0),
contradictionCount: clusterItems.reduce((sum, item) => sum + item.contradictionCount, 0),
...(clusterItems[0]?.updatedAt ? { updatedAt: clusterItems[0].updatedAt } : {}),
items: clusterItems,
} satisfies MemoryWikiPalaceCluster;
return Object.assign(
{
key: kind,
label: PALACE_KIND_LABELS[kind],
itemCount: clusterItems.length,
claimCount: clusterItems.reduce((sum, item) => sum + item.claimCount, 0),
questionCount: clusterItems.reduce((sum, item) => sum + item.questionCount, 0),
contradictionCount: clusterItems.reduce((sum, item) => sum + item.contradictionCount, 0),
},
clusterItems[0]?.updatedAt ? { updatedAt: clusterItems[0].updatedAt } : {},
{ items: clusterItems },
) satisfies MemoryWikiPalaceCluster;
}).filter((entry): entry is MemoryWikiPalaceCluster => entry !== null);
return {

View File

@@ -126,11 +126,13 @@ export const entraIdAuthMethod: ProviderAuthMethod = {
selectedResource,
resourceDeployments,
);
discoveredDeployments = resourceDeployments.map((deployment) => ({
name: deployment.name,
...(deployment.modelName ? { modelName: deployment.modelName } : {}),
api: resolveFoundryApi(deployment.name, deployment.modelName),
}));
discoveredDeployments = resourceDeployments.map((deployment) =>
Object.assign(
{ name: deployment.name },
deployment.modelName ? { modelName: deployment.modelName } : {},
{ api: resolveFoundryApi(deployment.name, deployment.modelName) },
),
);
endpoint = selectedResource.endpoint;
modelId = selectedDeployment.name;
modelNameHint = resolveConfiguredModelNameHint(modelId, selectedDeployment.modelName);

View File

@@ -301,17 +301,19 @@ export function buildFoundryProviderConfig(
deployment.modelName,
deployment.api,
);
return {
id: deployment.name,
name: capabilities.modelName,
api: capabilities.api,
reasoning: false,
input: capabilities.input,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 128_000,
maxTokens: 16_384,
...(capabilities.compat ? { compat: capabilities.compat } : {}),
};
return Object.assign(
{
id: deployment.name,
name: capabilities.modelName,
api: capabilities.api,
reasoning: false,
input: capabilities.input,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 128e3,
maxTokens: 16384,
},
capabilities.compat ? { compat: capabilities.compat } : {},
);
}),
};
}

View File

@@ -152,12 +152,14 @@ export function buildOpenAIImageGenerationProvider(): ImageGenerationProvider {
if (!entry.b64_json) {
return null;
}
return {
buffer: Buffer.from(entry.b64_json, "base64"),
mimeType: DEFAULT_OUTPUT_MIME,
fileName: `image-${index + 1}.png`,
...(entry.revised_prompt ? { revisedPrompt: entry.revised_prompt } : {}),
};
return Object.assign(
{
buffer: Buffer.from(entry.b64_json, `base64`),
mimeType: DEFAULT_OUTPUT_MIME,
fileName: `image-${index + 1}.png`,
},
entry.revised_prompt ? { revisedPrompt: entry.revised_prompt } : {},
);
})
.filter((entry): entry is NonNullable<typeof entry> => entry !== null);

View File

@@ -369,13 +369,20 @@ export function buildQaAgenticParityComparison(params: {
.map((name) => {
const candidate = candidateByName.get(name);
const baseline = baselineByName.get(name);
return {
const candidateStatus = candidate ? normalizeScenarioStatus(candidate.status) : "missing";
const baselineStatus = baseline ? normalizeScenarioStatus(baseline.status) : "missing";
const comparison: QaAgenticParityScenarioComparison = {
name,
candidateStatus: candidate ? normalizeScenarioStatus(candidate.status) : "missing",
baselineStatus: baseline ? normalizeScenarioStatus(baseline.status) : "missing",
...(candidate?.details ? { candidateDetails: candidate.details } : {}),
...(baseline?.details ? { baselineDetails: baseline.details } : {}),
} satisfies QaAgenticParityScenarioComparison;
candidateStatus,
baselineStatus,
};
if (candidate?.details) {
comparison.candidateDetails = candidate.details;
}
if (baseline?.details) {
comparison.baselineDetails = baseline.details;
}
return comparison;
});
const failures: string[] = [];

View File

@@ -86,11 +86,12 @@ function buildButtonsBlock(
}
return {
type: "buttons",
buttons: choices.map((choice) => ({
label: choice.label,
value: choice.value,
...(choice.style ? { style: choice.style } : {}),
})),
buttons: choices.map((choice) =>
Object.assign(
{ label: choice.label, value: choice.value },
choice.style ? { style: choice.style } : {},
),
),
};
}

View File

@@ -137,13 +137,17 @@ export async function runTavilySearch(
);
const rawResults = Array.isArray(payload.results) ? payload.results : [];
const results = rawResults.map((r: Record<string, unknown>) => ({
title: typeof r.title === "string" ? wrapWebContent(r.title, "web_search") : "",
url: typeof r.url === "string" ? r.url : "",
snippet: typeof r.content === "string" ? wrapWebContent(r.content, "web_search") : "",
score: typeof r.score === "number" ? r.score : undefined,
...(typeof r.published_date === "string" ? { published: r.published_date } : {}),
}));
const results = rawResults.map((r: Record<string, unknown>) =>
Object.assign(
{
title: typeof r.title === `string` ? wrapWebContent(r.title, `web_search`) : ``,
url: typeof r.url === `string` ? r.url : ``,
snippet: typeof r.content === `string` ? wrapWebContent(r.content, `web_search`) : ``,
score: typeof r.score === `number` ? r.score : undefined,
},
typeof r.published_date === `string` ? { published: r.published_date } : {},
),
);
const result: Record<string, unknown> = {
query: params.query,
@@ -227,23 +231,29 @@ export async function runTavilyExtract(
);
const rawResults = Array.isArray(payload.results) ? payload.results : [];
const results = rawResults.map((r: Record<string, unknown>) => ({
url: typeof r.url === "string" ? r.url : "",
rawContent:
typeof r.raw_content === "string"
? wrapExternalContent(r.raw_content, { source: "web_fetch", includeWarning: false })
: "",
...(typeof r.content === "string"
? { content: wrapExternalContent(r.content, { source: "web_fetch", includeWarning: false }) }
: {}),
...(Array.isArray(r.images)
? {
images: (r.images as string[]).map((img) =>
wrapExternalContent(img, { source: "web_fetch", includeWarning: false }),
),
}
: {}),
}));
const results = rawResults.map((r: Record<string, unknown>) =>
Object.assign(
{
url: typeof r.url === `string` ? r.url : ``,
rawContent:
typeof r.raw_content === `string`
? wrapExternalContent(r.raw_content, { source: `web_fetch`, includeWarning: false })
: ``,
},
typeof r.content === `string`
? {
content: wrapExternalContent(r.content, { source: `web_fetch`, includeWarning: false }),
}
: {},
Array.isArray(r.images)
? {
images: (r.images as string[]).map((img) =>
wrapExternalContent(img, { source: `web_fetch`, includeWarning: false }),
),
}
: {},
),
);
const failedResults = Array.isArray(payload.failed_results) ? payload.failed_results : [];

View File

@@ -12,11 +12,11 @@ export function buildInlineKeyboard(
row
.filter((button) => button?.text && button?.callback_data)
.map(
(button): InlineKeyboardButton => ({
text: button.text,
callback_data: button.callback_data,
...(button.style ? { style: button.style } : {}),
}),
(button): InlineKeyboardButton =>
Object.assign(
{ text: button.text, callback_data: button.callback_data },
button.style ? { style: button.style } : {},
),
),
)
.filter((row) => row.length > 0);

View File

@@ -277,10 +277,11 @@ export function createExtensionTestShards(params = {}) {
}
return shards
.map((shard, index) => ({
index,
checkName: `checks-node-extensions-shard-${index + 1}`,
...mergeTestPlans(shard.plans),
}))
.map((shard, index) =>
Object.assign(
{ index, checkName: `checks-node-extensions-shard-${index + 1}` },
mergeTestPlans(shard.plans),
),
)
.filter((shard) => shard.hasTests);
}

View File

@@ -157,13 +157,15 @@ export function resolveEffectiveToolInventory(
effectiveTools
.map((tool) => {
const source = resolveEffectiveToolSource(tool);
return {
id: tool.name,
label: resolveEffectiveToolLabel(tool),
description: summarizeToolDescription(tool),
rawDescription: resolveRawToolDescription(tool) || summarizeToolDescription(tool),
...source,
} satisfies EffectiveToolInventoryEntry;
return Object.assign(
{
id: tool.name,
label: resolveEffectiveToolLabel(tool),
description: summarizeToolDescription(tool),
rawDescription: resolveRawToolDescription(tool) || summarizeToolDescription(tool),
},
source,
) satisfies EffectiveToolInventoryEntry;
})
.toSorted((a, b) => a.label.localeCompare(b.label)),
);

View File

@@ -396,20 +396,24 @@ export function createImageGenerateTool(options?: {
const action = resolveAction(params);
if (action === "list") {
const runtimeProviders = listRuntimeImageGenerationProviders({ config: effectiveCfg });
const providers = runtimeProviders.map((provider) => ({
id: provider.id,
...(provider.label ? { label: provider.label } : {}),
...(provider.defaultModel ? { defaultModel: provider.defaultModel } : {}),
models: provider.models ?? (provider.defaultModel ? [provider.defaultModel] : []),
configured: isCapabilityProviderConfigured({
providers: runtimeProviders,
provider,
cfg: effectiveCfg,
agentDir: options?.agentDir,
}),
authEnvVars: getImageGenerationProviderAuthEnvVars(provider.id),
capabilities: provider.capabilities,
}));
const providers = runtimeProviders.map((provider) =>
Object.assign(
{ id: provider.id },
provider.label ? { label: provider.label } : {},
provider.defaultModel ? { defaultModel: provider.defaultModel } : {},
{
models: provider.models ?? (provider.defaultModel ? [provider.defaultModel] : []),
configured: isCapabilityProviderConfigured({
providers: runtimeProviders,
provider,
cfg: effectiveCfg,
agentDir: options?.agentDir,
}),
authEnvVars: getImageGenerationProviderAuthEnvVars(provider.id),
capabilities: provider.capabilities,
},
),
);
const lines = providers.flatMap((provider) => {
const caps: string[] = [];
if (provider.capabilities.edit.enabled) {

View File

@@ -524,10 +524,12 @@ export function createImageTool(options?: {
: {}),
}
: {
images: loadedImages.map((img) => ({
image: img.resolvedImage,
...(img.rewrittenFrom ? { rewrittenFrom: img.rewrittenFrom } : {}),
})),
images: loadedImages.map((img) =>
Object.assign(
{ image: img.resolvedImage },
img.rewrittenFrom ? { rewrittenFrom: img.rewrittenFrom } : {},
),
),
};
return buildTextToolResult(result, imageDetails);

View File

@@ -457,10 +457,12 @@ export function createPdfTool(options?: {
: {}),
}
: {
pdfs: loadedPdfs.map((p) => ({
pdf: p.resolvedPath,
...(p.rewrittenFrom ? { rewrittenFrom: p.rewrittenFrom } : {}),
})),
pdfs: loadedPdfs.map((p) =>
Object.assign(
{ pdf: p.resolvedPath },
p.rewrittenFrom ? { rewrittenFrom: p.rewrittenFrom } : {},
),
),
};
return buildTextToolResult(result, { native: result.native, ...pdfDetails });

View File

@@ -249,13 +249,17 @@ function mergeExecutionTrace(params: {
runner: "embedded" | "cli";
}): TraceExecutionView | undefined {
const attempts: TraceAttemptView[] = [
...(params.fallbackAttempts ?? []).map((attempt) => ({
provider: attempt.provider,
model: attempt.model,
result: inferFallbackAttemptResult(attempt),
...(attempt.reason ? { reason: attempt.reason } : {}),
...(typeof attempt.status === "number" ? { status: attempt.status } : {}),
})),
...(params.fallbackAttempts ?? []).map((attempt) =>
Object.assign(
{
provider: attempt.provider,
model: attempt.model,
result: inferFallbackAttemptResult(attempt),
},
attempt.reason ? { reason: attempt.reason } : {},
typeof attempt.status === `number` ? { status: attempt.status } : {},
),
),
...(params.executionTrace?.attempts ?? []),
];
const winnerProvider =

View File

@@ -1012,15 +1012,17 @@ async function runTtsProviders(transport: CapabilityTransport) {
...payload,
providers: (payload.providers ?? []).map((provider) => {
const id = typeof provider.id === "string" ? provider.id : "";
return {
available: true,
configured:
typeof provider.configured === "boolean"
? provider.configured
: providerHasGenericConfig({ cfg, providerId: id }),
selected: Boolean(id && payload.active === id),
...provider,
};
return Object.assign(
{
available: true,
configured:
typeof provider.configured === `boolean`
? provider.configured
: providerHasGenericConfig({ cfg, providerId: id }),
selected: Boolean(id && payload.active === id),
},
provider,
);
}),
};
}

View File

@@ -31,24 +31,27 @@ function resolveProviderChoiceOptions(params?: {
return resolveProviderSetupFlowContributions({
...params,
scope: "text-inference",
}).map((contribution) => ({
value: contribution.option.value as AuthChoice,
label: contribution.option.label,
...(contribution.option.hint ? { hint: contribution.option.hint } : {}),
...(contribution.option.assistantPriority !== undefined
? { assistantPriority: contribution.option.assistantPriority }
: {}),
...(contribution.option.assistantVisibility
? { assistantVisibility: contribution.option.assistantVisibility }
: {}),
...(contribution.option.group
? {
groupId: contribution.option.group.id as AuthChoiceGroupId,
groupLabel: contribution.option.group.label,
...(contribution.option.group.hint ? { groupHint: contribution.option.group.hint } : {}),
}
: {}),
}));
}).map((contribution) =>
Object.assign(
{ value: contribution.option.value as AuthChoice, label: contribution.option.label },
contribution.option.hint ? { hint: contribution.option.hint } : {},
contribution.option.assistantPriority !== undefined
? { assistantPriority: contribution.option.assistantPriority }
: {},
contribution.option.assistantVisibility
? { assistantVisibility: contribution.option.assistantVisibility }
: {},
contribution.option.group
? {
groupId: contribution.option.group.id as AuthChoiceGroupId,
groupLabel: contribution.option.group.label,
...(contribution.option.group.hint
? { groupHint: contribution.option.group.hint }
: {}),
}
: {},
),
);
}
export function formatAuthChoiceChoicesForCli(params?: {

View File

@@ -443,12 +443,12 @@ function setMergedSchemaCache(key: string, value: ConfigSchemaResponse): void {
function getBundledChannelSchemaMetadata(): ChannelUiMetadata[] {
return GENERATED_BUNDLED_CHANNEL_CONFIG_METADATA.map((entry) => {
const metadata: ChannelUiMetadata = {
id: entry.channelId,
...(entry.label ? { label: entry.label } : {}),
...(entry.description ? { description: entry.description } : {}),
configSchema: entry.schema,
};
const metadata: ChannelUiMetadata = Object.assign(
{ id: entry.channelId },
entry.label ? { label: entry.label } : {},
entry.description ? { description: entry.description } : {},
{ configSchema: entry.schema },
);
if ("uiHints" in entry) {
metadata.configUiHints = entry.uiHints as ChannelUiMetadata["configUiHints"];
}

View File

@@ -319,11 +319,12 @@ async function resolveProviderPluginSetupOptions(params: {
workspaceDir: params.workspaceDir,
env: params.env,
});
return providerModelPickerOptions.map((entry) => ({
value: entry.value,
label: entry.label,
...(entry.hint ? { hint: entry.hint } : {}),
}));
return providerModelPickerOptions.map((entry) =>
Object.assign(
{ value: entry.value, label: entry.label },
entry.hint ? { hint: entry.hint } : {},
),
);
}
async function maybeHandleProviderPluginSelection(params: {

View File

@@ -83,33 +83,37 @@ export function resolveProviderSetupFlowContributions(params?: {
return sortFlowContributionsByLabel(
resolveProviderWizardOptions(params ?? {})
.filter((option) => includesProviderFlowScope(option.onboardingScopes, scope))
.map((option) => ({
id: `provider:setup:${option.value}`,
kind: "provider" as const,
surface: "setup" as const,
providerId: option.groupId,
option: {
value: option.value,
label: option.label,
...(option.hint ? { hint: option.hint } : {}),
...(option.assistantPriority !== undefined
? { assistantPriority: option.assistantPriority }
: {}),
...(option.assistantVisibility
? { assistantVisibility: option.assistantVisibility }
: {}),
group: {
id: option.groupId,
label: option.groupLabel,
...(option.groupHint ? { hint: option.groupHint } : {}),
.map((option) =>
Object.assign(
{
id: `provider:setup:${option.value}`,
kind: `provider` as const,
surface: `setup` as const,
providerId: option.groupId,
option: {
value: option.value,
label: option.label,
...(option.hint ? { hint: option.hint } : {}),
...(option.assistantPriority !== undefined
? { assistantPriority: option.assistantPriority }
: {}),
...(option.assistantVisibility
? { assistantVisibility: option.assistantVisibility }
: {}),
group: {
id: option.groupId,
label: option.groupLabel,
...(option.groupHint ? { hint: option.groupHint } : {}),
},
...(docsByProvider.get(option.groupId)
? { docs: { path: docsByProvider.get(option.groupId)! } }
: {}),
},
},
...(docsByProvider.get(option.groupId)
? { docs: { path: docsByProvider.get(option.groupId)! } }
: {}),
},
...(option.onboardingScopes ? { onboardingScopes: [...option.onboardingScopes] } : {}),
source: "runtime" as const,
})),
option.onboardingScopes ? { onboardingScopes: [...option.onboardingScopes] } : {},
{ source: `runtime` as const },
),
),
);
}

View File

@@ -699,13 +699,15 @@ export function listAgentsForGateway(cfg: OpenClawConfig): {
const agents = agentIds.map((id) => {
const meta = configuredById.get(id);
const model = resolveGatewayAgentModel(cfg, id);
return {
id,
name: meta?.name,
identity: meta?.identity,
workspace: resolveAgentWorkspaceDir(cfg, id),
...(model ? { model } : {}),
};
return Object.assign(
{
id,
name: meta?.name,
identity: meta?.identity,
workspace: resolveAgentWorkspaceDir(cfg, id),
},
model ? { model } : {},
);
});
return { defaultId, mainKey, scope, agents };
}

View File

@@ -762,7 +762,7 @@ export async function loadSessionCostSummary(params: {
if (!stats) {
return null;
}
return { date, ...stats };
return Object.assign({ date }, stats);
})
.filter((entry): entry is SessionDailyLatency => Boolean(entry))
.toSorted((a, b) => a.date.localeCompare(b.date));

View File

@@ -98,10 +98,9 @@ describe("plugin shape compatibility matrix", () => {
workspaceDir: "/virtual-workspace",
...registry.registry,
};
const inspect = report.plugins.map((plugin) => ({
plugin,
...buildPluginShapeSummary({ plugin, report }),
}));
const inspect = report.plugins.map((plugin) =>
Object.assign({ plugin }, buildPluginShapeSummary({ plugin, report })),
);
expect(
inspect.map((entry) => ({

View File

@@ -97,18 +97,20 @@ export function buildConfigureCandidatesForScope(params: {
const refPathExists = entry.refPathSegments
? hasPathInAuthoredConfig(entry.refPathSegments)
: false;
return {
type: entry.entry.targetType,
path: entry.path,
pathSegments: [...entry.pathSegments],
label: entry.path,
configFile: "openclaw.json" as const,
expectedResolvedValue: entry.entry.expectedResolvedValue,
...(resolved.ref ? { existingRef: resolved.ref } : {}),
...(pathExists || refPathExists ? {} : { isDerived: true }),
...(entry.providerId ? { providerId: entry.providerId } : {}),
...(entry.accountId ? { accountId: entry.accountId } : {}),
};
return Object.assign(
{
type: entry.entry.targetType,
path: entry.path,
pathSegments: [...entry.pathSegments],
label: entry.path,
configFile: `openclaw.json` as const,
expectedResolvedValue: entry.entry.expectedResolvedValue,
},
resolved.ref ? { existingRef: resolved.ref } : {},
pathExists || refPathExists ? {} : { isDerived: true },
entry.providerId ? { providerId: entry.providerId } : {},
entry.accountId ? { accountId: entry.accountId } : {},
);
});
const authCandidates =
@@ -130,17 +132,19 @@ export function buildConfigureCandidatesForScope(params: {
refValue: entry.refValue,
defaults: params.config.secrets?.defaults,
});
return {
type: entry.entry.targetType,
path: entry.path,
pathSegments: [...entry.pathSegments],
label: `${entry.path} (auth profile, agent ${authProfiles.agentId})`,
configFile: "auth-profiles.json" as const,
expectedResolvedValue: entry.entry.expectedResolvedValue,
...(resolved.ref ? { existingRef: resolved.ref } : {}),
agentId: authProfiles.agentId,
...(authProfileProvider ? { authProfileProvider } : {}),
};
return Object.assign(
{
type: entry.entry.targetType,
path: entry.path,
pathSegments: [...entry.pathSegments],
label: `${entry.path} (auth profile, agent ${authProfiles.agentId})`,
configFile: `auth-profiles.json` as const,
expectedResolvedValue: entry.entry.expectedResolvedValue,
},
resolved.ref ? { existingRef: resolved.ref } : {},
{ agentId: authProfiles.agentId },
authProfileProvider ? { authProfileProvider } : {},
);
});
return [...openclawCandidates, ...authCandidates].toSorted((a, b) =>
@@ -234,16 +238,20 @@ export function buildSecretsConfigurePlan(params: {
protocolVersion: 1,
generatedAt: params.generatedAt ?? new Date().toISOString(),
generatedBy: "openclaw secrets configure",
targets: [...params.selectedTargets.values()].map((entry) => ({
type: entry.type,
path: entry.path,
pathSegments: [...entry.pathSegments],
ref: entry.ref,
...(entry.agentId ? { agentId: entry.agentId } : {}),
...(entry.providerId ? { providerId: entry.providerId } : {}),
...(entry.accountId ? { accountId: entry.accountId } : {}),
...(entry.authProfileProvider ? { authProfileProvider: entry.authProfileProvider } : {}),
})),
targets: [...params.selectedTargets.values()].map((entry) =>
Object.assign(
{
type: entry.type,
path: entry.path,
pathSegments: [...entry.pathSegments],
ref: entry.ref,
},
entry.agentId ? { agentId: entry.agentId } : {},
entry.providerId ? { providerId: entry.providerId } : {},
entry.accountId ? { accountId: entry.accountId } : {},
entry.authProfileProvider ? { authProfileProvider: entry.authProfileProvider } : {},
),
),
...(Object.keys(params.providerChanges.upserts).length > 0
? { providerUpserts: params.providerChanges.upserts }
: {}),

View File

@@ -33,18 +33,15 @@ export function buildSecretRefCredentialMatrix(): SecretRefCredentialMatrixDocum
? "tools.web.fetch.firecrawl.apiKey"
: entry.pathPattern;
return {
id: canonicalId,
configFile: entry.configFile,
path: canonicalPath,
...(entry.refPathPattern ? { refPath: entry.refPathPattern } : {}),
...(entry.authProfileType ? { when: { type: entry.authProfileType } } : {}),
secretShape: entry.secretShape,
optIn: true as const,
...(entry.secretShape === "sibling_ref" && entry.refPathPattern
? { notes: "Compatibility exception: sibling ref field remains canonical." }
: {}),
};
return Object.assign(
{ id: canonicalId, configFile: entry.configFile, path: canonicalPath },
entry.refPathPattern ? { refPath: entry.refPathPattern } : {},
entry.authProfileType ? { when: { type: entry.authProfileType } } : {},
{ secretShape: entry.secretShape, optIn: true as const },
entry.secretShape === `sibling_ref` && entry.refPathPattern
? { notes: `Compatibility exception: sibling ref field remains canonical.` }
: {},
);
})
.toSorted((a, b) => a.id.localeCompare(b.id));

View File

@@ -38,15 +38,14 @@ function loadCoverageRegistryEntries(): SecretRegistryEntry[] {
"secretref-user-supplied-credentials-matrix.json",
);
const matrix = JSON.parse(fs.readFileSync(matrixPath, "utf8")) as SecretRefCredentialMatrix;
return matrix.entries.map((entry) => ({
id: entry.id,
configFile: entry.configFile,
pathPattern: entry.path,
...(entry.refPath ? { refPathPattern: entry.refPath } : {}),
secretShape: entry.secretShape,
expectedResolvedValue: "string",
...(entry.when?.type ? { authProfileType: entry.when.type } : {}),
}));
return matrix.entries.map((entry) =>
Object.assign(
{ id: entry.id, configFile: entry.configFile, pathPattern: entry.path },
entry.refPath ? { refPathPattern: entry.refPath } : {},
{ secretShape: entry.secretShape, expectedResolvedValue: "string" as const },
entry.when?.type ? { authProfileType: entry.when.type } : {},
),
);
}
const COVERAGE_REGISTRY_ENTRIES = loadCoverageRegistryEntries();

View File

@@ -226,27 +226,29 @@ function toResolvedPlanTarget(
}
export function listSecretTargetRegistryEntries(): SecretTargetRegistryEntry[] {
return getCompiledSecretTargetRegistryState().compiledSecretTargetRegistry.map((entry) => ({
id: entry.id,
targetType: entry.targetType,
...(entry.targetTypeAliases ? { targetTypeAliases: [...entry.targetTypeAliases] } : {}),
configFile: entry.configFile,
pathPattern: entry.pathPattern,
...(entry.refPathPattern ? { refPathPattern: entry.refPathPattern } : {}),
secretShape: entry.secretShape,
expectedResolvedValue: entry.expectedResolvedValue,
includeInPlan: entry.includeInPlan,
includeInConfigure: entry.includeInConfigure,
includeInAudit: entry.includeInAudit,
...(entry.providerIdPathSegmentIndex !== undefined
? { providerIdPathSegmentIndex: entry.providerIdPathSegmentIndex }
: {}),
...(entry.accountIdPathSegmentIndex !== undefined
? { accountIdPathSegmentIndex: entry.accountIdPathSegmentIndex }
: {}),
...(entry.authProfileType ? { authProfileType: entry.authProfileType } : {}),
...(entry.trackProviderShadowing ? { trackProviderShadowing: true } : {}),
}));
return getCompiledSecretTargetRegistryState().compiledSecretTargetRegistry.map((entry) =>
Object.assign(
{ id: entry.id, targetType: entry.targetType },
entry.targetTypeAliases ? { targetTypeAliases: [...entry.targetTypeAliases] } : {},
{ configFile: entry.configFile, pathPattern: entry.pathPattern },
entry.refPathPattern ? { refPathPattern: entry.refPathPattern } : {},
{
secretShape: entry.secretShape,
expectedResolvedValue: entry.expectedResolvedValue,
includeInPlan: entry.includeInPlan,
includeInConfigure: entry.includeInConfigure,
includeInAudit: entry.includeInAudit,
},
entry.providerIdPathSegmentIndex !== undefined
? { providerIdPathSegmentIndex: entry.providerIdPathSegmentIndex }
: {},
entry.accountIdPathSegmentIndex !== undefined
? { accountIdPathSegmentIndex: entry.accountIdPathSegmentIndex }
: {},
entry.authProfileType ? { authProfileType: entry.authProfileType } : {},
entry.trackProviderShadowing ? { trackProviderShadowing: true } : {},
),
);
}
export function isKnownSecretTargetType(value: unknown): value is string {

View File

@@ -623,9 +623,8 @@ const sessionBindingContractEntries: Record<
let sessionBindingContractRegistryCache: SessionBindingContractEntry[] | undefined;
export function getSessionBindingContractRegistry(): SessionBindingContractEntry[] {
sessionBindingContractRegistryCache ??= sessionBindingContractChannelIds.map((id) => ({
id,
...sessionBindingContractEntries[id],
}));
sessionBindingContractRegistryCache ??= sessionBindingContractChannelIds.map((id) =>
Object.assign({ id }, sessionBindingContractEntries[id]),
);
return sessionBindingContractRegistryCache;
}

View File

@@ -369,11 +369,13 @@ function normalizeCommandEntry(
choices: getArgChoices(arg).slice(0, MAX_REMOTE_CHOICES),
}))
.filter((arg) => arg.name.length > 0)
.map((arg) => ({
name: arg.name,
...(arg.required ? { required: true } : {}),
...(arg.choices.length > 0 ? { choices: arg.choices } : {}),
}));
.map((arg) =>
Object.assign(
{ name: arg.name },
arg.required ? { required: true } : {},
arg.choices.length > 0 ? { choices: arg.choices } : {},
),
);
return {
key: primaryName,
name: primaryName,