From 1f1ff0567a015c53baf64444e949235a69c35f83 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 18 Apr 2026 19:13:36 +0100 Subject: [PATCH] refactor(lint): reduce map spread patterns --- ...ge-for-targetid.extension-fallback.test.ts | 9 +-- .../discord/src/actions/runtime.presence.ts | 13 ++-- .../src/exa-web-search-provider.runtime.ts | 20 ++--- extensions/googlechat/src/api.ts | 10 ++- extensions/memory-wiki/src/import-insights.ts | 28 +++---- extensions/memory-wiki/src/memory-palace.ts | 56 +++++++------- extensions/microsoft-foundry/auth.ts | 12 +-- extensions/microsoft-foundry/shared.ts | 24 +++--- .../openai/image-generation-provider.ts | 14 ++-- .../qa-lab/src/agentic-parity-report.ts | 19 +++-- extensions/slack/src/interactive-replies.ts | 11 +-- extensions/tavily/src/tavily-client.ts | 58 +++++++++------ extensions/telegram/src/inline-keyboard.ts | 10 +-- scripts/lib/extension-test-plan.mjs | 11 +-- src/agents/tools-effective-inventory.ts | 16 ++-- src/agents/tools/image-generate-tool.ts | 32 ++++---- src/agents/tools/image-tool.ts | 10 ++- src/agents/tools/pdf-tool.ts | 10 ++- src/auto-reply/reply/agent-runner.ts | 18 +++-- src/cli/capability-cli.ts | 20 ++--- src/commands/auth-choice-options.ts | 39 +++++----- src/config/schema.ts | 12 +-- src/flows/model-picker.ts | 11 +-- src/flows/provider-flow.ts | 56 +++++++------- src/gateway/session-utils.ts | 16 ++-- src/infra/session-cost-usage.ts | 2 +- src/plugins/contracts/shape.contract.test.ts | 7 +- src/secrets/configure-plan.ts | 74 ++++++++++--------- src/secrets/credential-matrix.ts | 21 +++--- src/secrets/runtime.coverage.test.ts | 17 ++--- src/secrets/target-registry-query.ts | 44 +++++------ .../channels/registry-session-binding.ts | 7 +- ui/src/ui/chat/slash-commands.ts | 12 +-- 33 files changed, 391 insertions(+), 328 deletions(-) diff --git a/extensions/browser/src/browser/pw-session.get-page-for-targetid.extension-fallback.test.ts b/extensions/browser/src/browser/pw-session.get-page-for-targetid.extension-fallback.test.ts index 2b3bdb32bd8..36c5dd24e37 100644 --- a/extensions/browser/src/browser/pw-session.get-page-for-targetid.extension-fallback.test.ts +++ b/extensions/browser/src/browser/pw-session.get-page-for-targetid.extension-fallback.test.ts @@ -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; diff --git a/extensions/discord/src/actions/runtime.presence.ts b/extensions/discord/src/actions/runtime.presence.ts index 3899fa222f9..26dfdf7ce98 100644 --- a/extensions/discord/src/actions/runtime.presence.ts +++ b/extensions/discord/src/actions/runtime.presence.ts @@ -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 } : {}, + ), + ), }); } diff --git a/extensions/exa/src/exa-web-search-provider.runtime.ts b/extensions/exa/src/exa-web-search-provider.runtime.ts index 84b1f2c0e7a..5f5dde0c5f9 100644 --- a/extensions/exa/src/exa-web-search-provider.runtime.ts +++ b/extensions/exa/src/exa-web-search-provider.runtime.ts @@ -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 } : {}, + ); }), }; diff --git a/extensions/googlechat/src/api.ts b/extensions/googlechat/src/api.ts index 2120256c2fa..c301a556358 100644 --- a/extensions/googlechat/src/api.ts +++ b/extensions/googlechat/src/api.ts @@ -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) { diff --git a/extensions/memory-wiki/src/import-insights.ts b/extensions/memory-wiki/src/import-insights.ts index be610fd28ec..745cdc5a1ae 100644 --- a/extensions/memory-wiki/src/import-insights.ts +++ b/extensions/memory-wiki/src/import-insights.ts @@ -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 ?? ""; diff --git a/extensions/memory-wiki/src/memory-palace.ts b/extensions/memory-wiki/src/memory-palace.ts index 777536b2243..09ddf237f31 100644 --- a/extensions/memory-wiki/src/memory-palace.ts +++ b/extensions/memory-wiki/src/memory-palace.ts @@ -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 { diff --git a/extensions/microsoft-foundry/auth.ts b/extensions/microsoft-foundry/auth.ts index f92aa1ee9b1..b58f6011403 100644 --- a/extensions/microsoft-foundry/auth.ts +++ b/extensions/microsoft-foundry/auth.ts @@ -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); diff --git a/extensions/microsoft-foundry/shared.ts b/extensions/microsoft-foundry/shared.ts index c42f23d2770..57838b3a2d2 100644 --- a/extensions/microsoft-foundry/shared.ts +++ b/extensions/microsoft-foundry/shared.ts @@ -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 } : {}, + ); }), }; } diff --git a/extensions/openai/image-generation-provider.ts b/extensions/openai/image-generation-provider.ts index ca7fb50cc06..945b51d82f4 100644 --- a/extensions/openai/image-generation-provider.ts +++ b/extensions/openai/image-generation-provider.ts @@ -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 => entry !== null); diff --git a/extensions/qa-lab/src/agentic-parity-report.ts b/extensions/qa-lab/src/agentic-parity-report.ts index d057ceffb6c..b1742631956 100644 --- a/extensions/qa-lab/src/agentic-parity-report.ts +++ b/extensions/qa-lab/src/agentic-parity-report.ts @@ -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[] = []; diff --git a/extensions/slack/src/interactive-replies.ts b/extensions/slack/src/interactive-replies.ts index 55f3a499ac1..39fc1815200 100644 --- a/extensions/slack/src/interactive-replies.ts +++ b/extensions/slack/src/interactive-replies.ts @@ -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 } : {}, + ), + ), }; } diff --git a/extensions/tavily/src/tavily-client.ts b/extensions/tavily/src/tavily-client.ts index eb1b5310df1..67f83c44720 100644 --- a/extensions/tavily/src/tavily-client.ts +++ b/extensions/tavily/src/tavily-client.ts @@ -137,13 +137,17 @@ export async function runTavilySearch( ); const rawResults = Array.isArray(payload.results) ? payload.results : []; - const results = rawResults.map((r: Record) => ({ - 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) => + 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 = { 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) => ({ - 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) => + 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 : []; diff --git a/extensions/telegram/src/inline-keyboard.ts b/extensions/telegram/src/inline-keyboard.ts index 981c4360f8d..d8ae4b1ea1f 100644 --- a/extensions/telegram/src/inline-keyboard.ts +++ b/extensions/telegram/src/inline-keyboard.ts @@ -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); diff --git a/scripts/lib/extension-test-plan.mjs b/scripts/lib/extension-test-plan.mjs index 191ef850627..b03c65bbaa8 100644 --- a/scripts/lib/extension-test-plan.mjs +++ b/scripts/lib/extension-test-plan.mjs @@ -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); } diff --git a/src/agents/tools-effective-inventory.ts b/src/agents/tools-effective-inventory.ts index 47d7d93c947..21f0241c961 100644 --- a/src/agents/tools-effective-inventory.ts +++ b/src/agents/tools-effective-inventory.ts @@ -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)), ); diff --git a/src/agents/tools/image-generate-tool.ts b/src/agents/tools/image-generate-tool.ts index 6cb97318ab0..d94b9323706 100644 --- a/src/agents/tools/image-generate-tool.ts +++ b/src/agents/tools/image-generate-tool.ts @@ -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) { diff --git a/src/agents/tools/image-tool.ts b/src/agents/tools/image-tool.ts index 168c1d60174..e94481447b7 100644 --- a/src/agents/tools/image-tool.ts +++ b/src/agents/tools/image-tool.ts @@ -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); diff --git a/src/agents/tools/pdf-tool.ts b/src/agents/tools/pdf-tool.ts index c0873805eab..3b45bcc4610 100644 --- a/src/agents/tools/pdf-tool.ts +++ b/src/agents/tools/pdf-tool.ts @@ -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 }); diff --git a/src/auto-reply/reply/agent-runner.ts b/src/auto-reply/reply/agent-runner.ts index 6b4d21d65d6..5b90e983ffb 100644 --- a/src/auto-reply/reply/agent-runner.ts +++ b/src/auto-reply/reply/agent-runner.ts @@ -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 = diff --git a/src/cli/capability-cli.ts b/src/cli/capability-cli.ts index 419722b11d1..a98c674e7b3 100644 --- a/src/cli/capability-cli.ts +++ b/src/cli/capability-cli.ts @@ -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, + ); }), }; } diff --git a/src/commands/auth-choice-options.ts b/src/commands/auth-choice-options.ts index cb799db2fb7..75959235dc1 100644 --- a/src/commands/auth-choice-options.ts +++ b/src/commands/auth-choice-options.ts @@ -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?: { diff --git a/src/config/schema.ts b/src/config/schema.ts index 067d9639020..ead14626230 100644 --- a/src/config/schema.ts +++ b/src/config/schema.ts @@ -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"]; } diff --git a/src/flows/model-picker.ts b/src/flows/model-picker.ts index bec3ca7df78..6a9095f7935 100644 --- a/src/flows/model-picker.ts +++ b/src/flows/model-picker.ts @@ -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: { diff --git a/src/flows/provider-flow.ts b/src/flows/provider-flow.ts index e14f2db25e9..06c9cb10bed 100644 --- a/src/flows/provider-flow.ts +++ b/src/flows/provider-flow.ts @@ -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 }, + ), + ), ); } diff --git a/src/gateway/session-utils.ts b/src/gateway/session-utils.ts index 6e1e8f1f86b..282b93f79b6 100644 --- a/src/gateway/session-utils.ts +++ b/src/gateway/session-utils.ts @@ -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 }; } diff --git a/src/infra/session-cost-usage.ts b/src/infra/session-cost-usage.ts index f2066c5a14c..a7656dee8f3 100644 --- a/src/infra/session-cost-usage.ts +++ b/src/infra/session-cost-usage.ts @@ -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)); diff --git a/src/plugins/contracts/shape.contract.test.ts b/src/plugins/contracts/shape.contract.test.ts index f121d0e100c..29ff4fd423b 100644 --- a/src/plugins/contracts/shape.contract.test.ts +++ b/src/plugins/contracts/shape.contract.test.ts @@ -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) => ({ diff --git a/src/secrets/configure-plan.ts b/src/secrets/configure-plan.ts index 62be11f96ac..d38e8700149 100644 --- a/src/secrets/configure-plan.ts +++ b/src/secrets/configure-plan.ts @@ -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 } : {}), diff --git a/src/secrets/credential-matrix.ts b/src/secrets/credential-matrix.ts index 1ee443ed16e..649d3e6fc84 100644 --- a/src/secrets/credential-matrix.ts +++ b/src/secrets/credential-matrix.ts @@ -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)); diff --git a/src/secrets/runtime.coverage.test.ts b/src/secrets/runtime.coverage.test.ts index 0f3ff190870..ba7e0bf09d5 100644 --- a/src/secrets/runtime.coverage.test.ts +++ b/src/secrets/runtime.coverage.test.ts @@ -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(); diff --git a/src/secrets/target-registry-query.ts b/src/secrets/target-registry-query.ts index c0d8607fc70..cc42ada89e9 100644 --- a/src/secrets/target-registry-query.ts +++ b/src/secrets/target-registry-query.ts @@ -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 { diff --git a/test/helpers/channels/registry-session-binding.ts b/test/helpers/channels/registry-session-binding.ts index d126c30f89f..fb4b48a1d8c 100644 --- a/test/helpers/channels/registry-session-binding.ts +++ b/test/helpers/channels/registry-session-binding.ts @@ -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; } diff --git a/ui/src/ui/chat/slash-commands.ts b/ui/src/ui/chat/slash-commands.ts index 29fd51666d2..af4b69d43af 100644 --- a/ui/src/ui/chat/slash-commands.ts +++ b/ui/src/ui/chat/slash-commands.ts @@ -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,