mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
refactor(lint): enable map spread rule
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
"eslint-plugin-unicorn/prefer-set-size": "error",
|
||||
"oxc/no-accumulating-spread": "error",
|
||||
"oxc/no-async-endpoint-handlers": "error",
|
||||
"oxc/no-map-spread": "off",
|
||||
"oxc/no-map-spread": "error",
|
||||
"typescript/consistent-return": "error",
|
||||
"typescript/no-explicit-any": "error",
|
||||
"typescript/no-extraneous-class": "error",
|
||||
@@ -55,7 +55,8 @@
|
||||
{
|
||||
"files": ["src/security/**"],
|
||||
"rules": {
|
||||
"eslint/no-warning-comments": "off"
|
||||
"eslint/no-warning-comments": "off",
|
||||
"oxc/no-map-spread": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -36,10 +36,9 @@ export function buildArceeCatalogModels(): NonNullable<ModelProviderConfig["mode
|
||||
}
|
||||
|
||||
export function buildArceeOpenRouterCatalogModels(): NonNullable<ModelProviderConfig["models"]> {
|
||||
return buildArceeCatalogModels().map((model) => ({
|
||||
...model,
|
||||
id: toArceeOpenRouterModelId(model.id),
|
||||
}));
|
||||
return buildArceeCatalogModels().map((model) =>
|
||||
Object.assign({}, model, { id: toArceeOpenRouterModelId(model.id) }),
|
||||
);
|
||||
}
|
||||
|
||||
export function buildArceeProvider(): ModelProviderConfig {
|
||||
|
||||
@@ -25,10 +25,11 @@ export const listDiscordDirectoryPeersFromConfig = createResolvedDirectoryEntrie
|
||||
resolveAccount: (cfg, accountId) => resolveDiscordDirectoryConfigAccount(cfg, accountId),
|
||||
resolveSources: (account) => {
|
||||
const allowFrom = account.config.allowFrom ?? account.config.dm?.allowFrom ?? [];
|
||||
const guildUsers = Object.values(account.config.guilds ?? {}).flatMap((guild) => [
|
||||
...(guild.users ?? []),
|
||||
...Object.values(guild.channels ?? {}).flatMap((channel) => channel.users ?? []),
|
||||
]);
|
||||
const guildUsers = Object.values(account.config.guilds ?? {}).flatMap((guild) =>
|
||||
(guild.users ?? []).concat(
|
||||
Object.values(guild.channels ?? {}).flatMap((channel) => channel.users ?? []),
|
||||
),
|
||||
);
|
||||
return [allowFrom, Object.keys(account.config.dms ?? {}), guildUsers];
|
||||
},
|
||||
normalizeId: (raw) => {
|
||||
|
||||
@@ -110,7 +110,7 @@ function cleanBlocksForInsert(blocks: FeishuDocxBlock[]): {
|
||||
.map((block) => {
|
||||
if (block.block_type === 31 && block.table?.merge_info) {
|
||||
const { merge_info: _merge_info, ...tableRest } = block.table;
|
||||
return { ...block, table: tableRest };
|
||||
return Object.assign({}, block, { table: tableRest });
|
||||
}
|
||||
return block;
|
||||
});
|
||||
|
||||
@@ -141,7 +141,7 @@ function normalizeProviderModels(
|
||||
return model;
|
||||
}
|
||||
mutated = true;
|
||||
return { ...model, id: nextId };
|
||||
return Object.assign({}, model, { id: nextId });
|
||||
});
|
||||
|
||||
return mutated ? { ...provider, models: nextModels } : provider;
|
||||
|
||||
@@ -120,10 +120,9 @@ async function runGeminiSearch(params: {
|
||||
for (let index = 0; index < rawCitations.length; index += 10) {
|
||||
const batch = rawCitations.slice(index, index + 10);
|
||||
const resolved = await Promise.all(
|
||||
batch.map(async (citation) => ({
|
||||
...citation,
|
||||
url: await resolveCitationRedirectUrl(citation.url),
|
||||
})),
|
||||
batch.map(async (citation) =>
|
||||
Object.assign({}, citation, { url: await resolveCitationRedirectUrl(citation.url) }),
|
||||
),
|
||||
);
|
||||
citations.push(...resolved);
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ export const ircPlugin: ChannelPlugin<ResolvedIrcAccount, IrcProbe> = createChat
|
||||
listPeers: async (params) => listIrcDirectoryPeersFromConfig(params),
|
||||
listGroups: async (params) => {
|
||||
const entries = await listIrcDirectoryGroupsFromConfig(params);
|
||||
return entries.map((entry) => ({ ...entry, name: entry.id }));
|
||||
return entries.map((entry) => Object.assign({}, entry, { name: entry.id }));
|
||||
},
|
||||
}),
|
||||
status: createComputedAccountStatusAdapter<ResolvedIrcAccount, IrcProbe>({
|
||||
|
||||
@@ -817,10 +817,11 @@ export async function prepareLmstudioDynamicModels(
|
||||
headers,
|
||||
quiet: true,
|
||||
});
|
||||
return discoveredModels.map((model) => ({
|
||||
...model,
|
||||
provider: PROVIDER_ID,
|
||||
api: ctx.providerConfig?.api ?? "openai-completions",
|
||||
baseUrl,
|
||||
}));
|
||||
return discoveredModels.map((model) =>
|
||||
Object.assign({}, model, {
|
||||
provider: PROVIDER_ID,
|
||||
api: ctx.providerConfig?.api ?? `openai-completions`,
|
||||
baseUrl,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -364,7 +364,9 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount, MatrixProbe> =
|
||||
return entries.map((entry) => {
|
||||
const raw = entry.id.startsWith("user:") ? entry.id.slice("user:".length) : entry.id;
|
||||
const incomplete = !raw.startsWith("@") || !raw.includes(":");
|
||||
return incomplete ? { ...entry, name: "incomplete id; expected @user:server" } : entry;
|
||||
return incomplete
|
||||
? Object.assign({}, entry, { name: `incomplete id; expected @user:server` })
|
||||
: entry;
|
||||
});
|
||||
},
|
||||
listGroups: async (params) => await listMatrixDirectoryGroupsFromConfig(params),
|
||||
|
||||
@@ -840,35 +840,45 @@ function buildAgentDigest(params: {
|
||||
.toSorted((left, right) => left.relativePath.localeCompare(right.relativePath))
|
||||
.map((page) => {
|
||||
const pageFreshness = assessPageFreshness(page);
|
||||
return {
|
||||
...(page.id ? { id: page.id } : {}),
|
||||
title: page.title,
|
||||
kind: page.kind,
|
||||
path: page.relativePath,
|
||||
sourceIds: [...page.sourceIds],
|
||||
questions: [...page.questions],
|
||||
contradictions: [...page.contradictions],
|
||||
...(typeof page.confidence === "number" ? { confidence: page.confidence } : {}),
|
||||
freshnessLevel: pageFreshness.level,
|
||||
...(pageFreshness.lastTouchedAt ? { lastTouchedAt: pageFreshness.lastTouchedAt } : {}),
|
||||
claimCount: page.claims.length,
|
||||
topClaims: sortClaims(page)
|
||||
.slice(0, 5)
|
||||
.map((claim) => {
|
||||
const freshness = assessClaimFreshness({ page, claim });
|
||||
return {
|
||||
...(claim.id ? { id: claim.id } : {}),
|
||||
text: claim.text,
|
||||
status: normalizeClaimStatus(claim.status),
|
||||
...(typeof claim.confidence === "number" ? { confidence: claim.confidence } : {}),
|
||||
evidenceCount: claim.evidence.length,
|
||||
missingEvidence: claim.evidence.length === 0,
|
||||
evidence: [...claim.evidence],
|
||||
freshnessLevel: freshness.level,
|
||||
...(freshness.lastTouchedAt ? { lastTouchedAt: freshness.lastTouchedAt } : {}),
|
||||
};
|
||||
}),
|
||||
};
|
||||
return Object.assign(
|
||||
{},
|
||||
page.id ? { id: page.id } : {},
|
||||
{
|
||||
title: page.title,
|
||||
kind: page.kind,
|
||||
path: page.relativePath,
|
||||
sourceIds: [...page.sourceIds],
|
||||
questions: [...page.questions],
|
||||
contradictions: [...page.contradictions],
|
||||
},
|
||||
typeof page.confidence === "number" ? { confidence: page.confidence } : {},
|
||||
{ freshnessLevel: pageFreshness.level },
|
||||
pageFreshness.lastTouchedAt ? { lastTouchedAt: pageFreshness.lastTouchedAt } : {},
|
||||
{
|
||||
claimCount: page.claims.length,
|
||||
topClaims: sortClaims(page)
|
||||
.slice(0, 5)
|
||||
.map((claim) => {
|
||||
const freshness = assessClaimFreshness({ page, claim });
|
||||
return Object.assign(
|
||||
{},
|
||||
claim.id ? { id: claim.id } : {},
|
||||
{
|
||||
text: claim.text,
|
||||
status: normalizeClaimStatus(claim.status),
|
||||
},
|
||||
typeof claim.confidence === "number" ? { confidence: claim.confidence } : {},
|
||||
{
|
||||
evidenceCount: claim.evidence.length,
|
||||
missingEvidence: claim.evidence.length === 0,
|
||||
evidence: [...claim.evidence],
|
||||
freshnessLevel: freshness.level,
|
||||
},
|
||||
freshness.lastTouchedAt ? { lastTouchedAt: freshness.lastTouchedAt } : {},
|
||||
);
|
||||
}),
|
||||
},
|
||||
);
|
||||
});
|
||||
return {
|
||||
pageCounts: params.pageCounts,
|
||||
|
||||
@@ -93,5 +93,7 @@ export function buildMistralModelDefinition(): ModelDefinitionConfig {
|
||||
}
|
||||
|
||||
export function buildMistralCatalogModels(): ModelDefinitionConfig[] {
|
||||
return MISTRAL_MODEL_CATALOG.map((model) => ({ ...model, input: [...model.input] }));
|
||||
return MISTRAL_MODEL_CATALOG.map((model) =>
|
||||
Object.assign({}, model, { input: [...model.input] }),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -75,6 +75,8 @@ export function buildMoonshotProvider(): ModelProviderConfig {
|
||||
return {
|
||||
baseUrl: MOONSHOT_BASE_URL,
|
||||
api: "openai-completions",
|
||||
models: MOONSHOT_MODEL_CATALOG.map((model) => ({ ...model, input: [...model.input] })),
|
||||
models: MOONSHOT_MODEL_CATALOG.map((model) =>
|
||||
Object.assign({}, model, { input: [...model.input] }),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -194,11 +194,10 @@ export async function enrichOllamaModelsWithContext(
|
||||
const batchResults = await Promise.all(
|
||||
batch.map(async (model) => {
|
||||
const showInfo = await queryOllamaModelShowInfoCached(apiBase, model);
|
||||
return {
|
||||
...model,
|
||||
return Object.assign({}, model, {
|
||||
contextWindow: showInfo.contextWindow,
|
||||
capabilities: showInfo.capabilities,
|
||||
};
|
||||
});
|
||||
}),
|
||||
);
|
||||
enriched.push(...batchResults);
|
||||
|
||||
@@ -85,10 +85,10 @@ export function buildQaBusSnapshot(params: {
|
||||
}): QaBusStateSnapshot {
|
||||
return {
|
||||
cursor: params.cursor,
|
||||
conversations: Array.from(params.conversations.values()).map((conversation) => ({
|
||||
...conversation,
|
||||
})),
|
||||
threads: Array.from(params.threads.values()).map((thread) => ({ ...thread })),
|
||||
conversations: Array.from(params.conversations.values()).map((conversation) =>
|
||||
Object.assign({}, conversation),
|
||||
),
|
||||
threads: Array.from(params.threads.values()).map((thread) => Object.assign({}, thread)),
|
||||
messages: Array.from(params.messages.values()).map((message) => cloneMessage(message)),
|
||||
events: params.events.map((event) => cloneEvent(event)),
|
||||
};
|
||||
|
||||
@@ -651,10 +651,10 @@ export async function runQaCharacterEval(params: QaCharacterEvalParams) {
|
||||
timeoutMs: judgeTimeoutMs,
|
||||
});
|
||||
rankings = parseJudgeReply(rawReply, new Set(judgePrompt.labelToModel.keys())).map(
|
||||
(ranking) => ({
|
||||
...ranking,
|
||||
model: judgePrompt.labelToModel.get(ranking.model) ?? ranking.model,
|
||||
}),
|
||||
(ranking) =>
|
||||
Object.assign({}, ranking, {
|
||||
model: judgePrompt.labelToModel.get(ranking.model) ?? ranking.model,
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
judgeError = formatErrorMessage(error);
|
||||
|
||||
@@ -6,7 +6,7 @@ export function buildQwenProvider(params?: { baseUrl?: string }): ModelProviderC
|
||||
return {
|
||||
baseUrl,
|
||||
api: "openai-completions",
|
||||
models: buildQwenModelCatalogForBaseUrl(baseUrl).map((model) => ({ ...model })),
|
||||
models: buildQwenModelCatalogForBaseUrl(baseUrl).map((model) => Object.assign({}, model)),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -446,7 +446,7 @@ export async function handleSlackAction(
|
||||
(pin.message as { ts?: unknown }).ts,
|
||||
)
|
||||
: pin.message;
|
||||
return message ? { ...pin, message } : pin;
|
||||
return message ? Object.assign({}, pin, { message }) : pin;
|
||||
});
|
||||
return jsonResult({ ok: true, pins: normalizedPins });
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ function fitTelegramCommandsWithinTextBudget(
|
||||
const description = truncateTelegramCommandText(command.description, descriptionCap);
|
||||
if (description !== command.description) {
|
||||
descriptionTrimmed = true;
|
||||
return { ...command, description };
|
||||
return Object.assign({}, command, { description });
|
||||
}
|
||||
return command;
|
||||
});
|
||||
|
||||
@@ -86,7 +86,7 @@ export function buildVydraSpeechProvider(): SpeechProviderPlugin {
|
||||
models: [DEFAULT_VYDRA_SPEECH_MODEL],
|
||||
voices: VYDRA_SPEECH_VOICES.map((voice) => voice.id),
|
||||
resolveConfig: ({ rawConfig }) => normalizeVydraSpeechConfig(rawConfig),
|
||||
listVoices: async () => VYDRA_SPEECH_VOICES.map((voice) => ({ ...voice })),
|
||||
listVoices: async () => VYDRA_SPEECH_VOICES.map((voice) => Object.assign({}, voice)),
|
||||
isConfigured: ({ providerConfig }) =>
|
||||
Boolean(readVydraSpeechConfig(providerConfig).apiKey || process.env.VYDRA_API_KEY),
|
||||
synthesize: async (req) => {
|
||||
|
||||
@@ -169,10 +169,9 @@ describe("web auto-reply", () => {
|
||||
const sharedRaw = crypto.randomBytes(width * height * 3);
|
||||
|
||||
const renderedFormats = await Promise.all(
|
||||
formats.map(async (fmt) => ({
|
||||
...fmt,
|
||||
image: await fmt.make(sharedRaw, { width, height }),
|
||||
})),
|
||||
formats.map(async (fmt) =>
|
||||
Object.assign({}, fmt, { image: await fmt.make(sharedRaw, { width, height }) }),
|
||||
),
|
||||
);
|
||||
|
||||
await withMediaCap(SMALL_MEDIA_CAP_MB, async () => {
|
||||
|
||||
@@ -215,10 +215,11 @@ export async function main() {
|
||||
}
|
||||
|
||||
const rows = Object.values(totalsByJob)
|
||||
.map((r) => ({
|
||||
...r,
|
||||
models: Object.values(r.models).toSorted((a, b) => b.total_tokens - a.total_tokens),
|
||||
}))
|
||||
.map((r) =>
|
||||
Object.assign({}, r, {
|
||||
models: Object.values(r.models).toSorted((a, b) => b.total_tokens - a.total_tokens),
|
||||
}),
|
||||
)
|
||||
.toSorted((a, b) => b.total_tokens - a.total_tokens);
|
||||
|
||||
if (asJson) {
|
||||
|
||||
@@ -197,11 +197,12 @@ function mergeTestPlans(plans) {
|
||||
}
|
||||
|
||||
const planGroups = [...groupsByConfig.values()]
|
||||
.map((group) => ({
|
||||
...group,
|
||||
extensionIds: group.extensionIds.toSorted((left, right) => left.localeCompare(right)),
|
||||
roots: [...new Set(group.roots)],
|
||||
}))
|
||||
.map((group) =>
|
||||
Object.assign({}, group, {
|
||||
extensionIds: group.extensionIds.toSorted((left, right) => left.localeCompare(right)),
|
||||
roots: [...new Set(group.roots)],
|
||||
}),
|
||||
)
|
||||
.toSorted((left, right) => left.config.localeCompare(right.config));
|
||||
|
||||
return {
|
||||
@@ -279,6 +280,7 @@ export function createExtensionTestShards(params = {}) {
|
||||
return shards
|
||||
.map((shard, index) =>
|
||||
Object.assign(
|
||||
{},
|
||||
{ index, checkName: `checks-node-extensions-shard-${index + 1}` },
|
||||
mergeTestPlans(shard.plans),
|
||||
),
|
||||
|
||||
@@ -352,17 +352,15 @@ export async function collectPluginClawHubReleasePlan(params?: {
|
||||
});
|
||||
|
||||
const all = await Promise.all(
|
||||
selectedPublishable.map(async (plugin) => ({
|
||||
...plugin,
|
||||
alreadyPublished: await isPluginVersionPublishedOnClawHub(
|
||||
plugin.packageName,
|
||||
plugin.version,
|
||||
{
|
||||
registryBaseUrl: params?.registryBaseUrl,
|
||||
fetchImpl: params?.fetchImpl,
|
||||
},
|
||||
),
|
||||
})),
|
||||
selectedPublishable.map(async (plugin) =>
|
||||
Object.assign({}, plugin, {
|
||||
alreadyPublished: await isPluginVersionPublishedOnClawHub(
|
||||
plugin.packageName,
|
||||
plugin.version,
|
||||
{ registryBaseUrl: params?.registryBaseUrl, fetchImpl: params?.fetchImpl },
|
||||
),
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -462,10 +462,11 @@ export function collectPluginReleasePlan(params?: {
|
||||
})
|
||||
: allPublishable;
|
||||
|
||||
const all = selectedPublishable.map((plugin) => ({
|
||||
...plugin,
|
||||
alreadyPublished: isPluginVersionPublished(plugin.packageName, plugin.version),
|
||||
}));
|
||||
const all = selectedPublishable.map((plugin) =>
|
||||
Object.assign({}, plugin, {
|
||||
alreadyPublished: isPluginVersionPublished(plugin.packageName, plugin.version),
|
||||
}),
|
||||
);
|
||||
|
||||
return {
|
||||
all,
|
||||
|
||||
@@ -167,12 +167,13 @@ export function resolveRunnerMatrix(params) {
|
||||
];
|
||||
return {
|
||||
include: runners.flatMap((runner) =>
|
||||
suites.map((suite) => ({
|
||||
...runner,
|
||||
suite,
|
||||
suite_label: formatSuiteLabel(suite),
|
||||
lane: suite.includes("upgrade") || suite === "dev-update" ? "upgrade" : "fresh",
|
||||
})),
|
||||
suites.map((suite) =>
|
||||
Object.assign({}, runner, {
|
||||
suite,
|
||||
suite_label: formatSuiteLabel(suite),
|
||||
lane: suite.includes(`upgrade`) || suite === `dev-update` ? `upgrade` : `fresh`,
|
||||
}),
|
||||
),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -449,10 +449,11 @@ export function discoverBundledPluginRuntimeDeps(params = {}) {
|
||||
}
|
||||
|
||||
return [...deps.values()]
|
||||
.map((dep) => ({
|
||||
...dep,
|
||||
pluginIds: [...dep.pluginIds].toSorted((a, b) => a.localeCompare(b)),
|
||||
}))
|
||||
.map((dep) =>
|
||||
Object.assign({}, dep, {
|
||||
pluginIds: [...dep.pluginIds].toSorted((a, b) => a.localeCompare(b)),
|
||||
}),
|
||||
)
|
||||
.toSorted((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
|
||||
|
||||
@@ -97,14 +97,17 @@ export function mergeProviderModels(
|
||||
implicitValue: implicitModel.maxTokens,
|
||||
});
|
||||
|
||||
return {
|
||||
...explicitModel,
|
||||
input: implicitModel.input,
|
||||
reasoning: "reasoning" in explicitModel ? explicitModel.reasoning : implicitModel.reasoning,
|
||||
...(contextWindow === undefined ? {} : { contextWindow }),
|
||||
...(contextTokens === undefined ? {} : { contextTokens }),
|
||||
...(maxTokens === undefined ? {} : { maxTokens }),
|
||||
};
|
||||
return Object.assign(
|
||||
{},
|
||||
explicitModel,
|
||||
{
|
||||
input: implicitModel.input,
|
||||
reasoning: `reasoning` in explicitModel ? explicitModel.reasoning : implicitModel.reasoning,
|
||||
},
|
||||
contextWindow === undefined ? {} : { contextWindow },
|
||||
contextTokens === undefined ? {} : { contextTokens },
|
||||
maxTokens === undefined ? {} : { maxTokens },
|
||||
);
|
||||
});
|
||||
|
||||
for (const implicitModel of implicitModels) {
|
||||
|
||||
@@ -126,7 +126,7 @@ vi.mock("@mariozechner/pi-ai", async () => {
|
||||
context: { messages?: Array<{ role?: string; content?: unknown }> },
|
||||
) => {
|
||||
streamCallCount += 1;
|
||||
const messages = (context.messages ?? []).map((message) => ({ ...message }));
|
||||
const messages = (context.messages ?? []).map((message) => Object.assign({}, message));
|
||||
observedContexts.push(messages);
|
||||
const stream = actual.createAssistantMessageEventStream();
|
||||
queueMicrotask(() => {
|
||||
|
||||
@@ -168,7 +168,7 @@ export function applyFinalEffectiveToolPolicy(
|
||||
}),
|
||||
{ policy: params.sandboxToolPolicy, label: "sandbox tools.allow" },
|
||||
{ policy: subagentPolicy, label: "subagent tools.allow" },
|
||||
].map((step) => ({ ...step, suppressUnavailableCoreToolWarning: true }));
|
||||
].map((step) => Object.assign({}, step, { suppressUnavailableCoreToolWarning: true }));
|
||||
return applyToolPolicyPipeline({
|
||||
tools: ownerFiltered,
|
||||
toolMeta: (tool) => getPluginToolMeta(tool),
|
||||
|
||||
@@ -288,13 +288,12 @@ export function truncateToolResultMessage(
|
||||
1,
|
||||
Math.min(maxChars, Math.max(minKeepChars + defaultSuffix.length, proportionalBudget)),
|
||||
);
|
||||
return {
|
||||
...textBlock,
|
||||
return Object.assign({}, textBlock, {
|
||||
text: truncateToolResultText(textBlock.text, blockBudget, {
|
||||
suffix: suffixFactory,
|
||||
minKeepChars,
|
||||
}),
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
return { ...msg, content: newContent } as AgentMessage;
|
||||
|
||||
@@ -105,14 +105,14 @@ export function sanitizeToolResult(result: unknown): unknown {
|
||||
const entry = item as Record<string, unknown>;
|
||||
const type = readStringValue(entry.type);
|
||||
if (type === "text" && typeof entry.text === "string") {
|
||||
return { ...entry, text: truncateToolText(entry.text) };
|
||||
return Object.assign({}, entry, { text: truncateToolText(entry.text) });
|
||||
}
|
||||
if (type === "image") {
|
||||
const data = readStringValue(entry.data);
|
||||
const bytes = data ? data.length : undefined;
|
||||
const cleaned = { ...entry };
|
||||
delete cleaned.data;
|
||||
return { ...cleaned, bytes, omitted: true };
|
||||
return Object.assign({}, cleaned, { bytes, omitted: true });
|
||||
}
|
||||
return entry;
|
||||
});
|
||||
|
||||
@@ -126,10 +126,7 @@ function withToolResultText(
|
||||
(block as { type?: unknown }).type === "text"
|
||||
) {
|
||||
replaced = true;
|
||||
return {
|
||||
...(block as TextContentBlock),
|
||||
text,
|
||||
};
|
||||
return Object.assign({}, block as TextContentBlock, { text });
|
||||
}
|
||||
return block;
|
||||
});
|
||||
@@ -332,7 +329,7 @@ async function normalizeReadImageResult(
|
||||
const nextContent = content.map((block) => {
|
||||
if (block && typeof block === "object" && (block as { type?: unknown }).type === "image") {
|
||||
const b = block as ImageContentBlock & { mimeType: string };
|
||||
return { ...b, mimeType: sniffed } satisfies ImageContentBlock;
|
||||
return Object.assign({}, b, { mimeType: sniffed }) satisfies ImageContentBlock;
|
||||
}
|
||||
if (
|
||||
block &&
|
||||
@@ -341,10 +338,9 @@ async function normalizeReadImageResult(
|
||||
typeof (block as { text?: unknown }).text === "string"
|
||||
) {
|
||||
const b = block as TextContentBlock & { text: string };
|
||||
return {
|
||||
...b,
|
||||
return Object.assign({}, b, {
|
||||
text: rewriteReadImageHeader(b.text, sniffed),
|
||||
} satisfies TextContentBlock;
|
||||
}) satisfies TextContentBlock;
|
||||
}
|
||||
return block;
|
||||
});
|
||||
|
||||
@@ -39,7 +39,7 @@ const coreTools = [
|
||||
];
|
||||
|
||||
vi.mock("../openclaw-tools.js", () => ({
|
||||
createOpenClawTools: () => coreTools.map((tool) => ({ ...tool })),
|
||||
createOpenClawTools: () => coreTools.map((tool) => Object.assign({}, tool)),
|
||||
__testing: {
|
||||
setDepsForTest: () => {},
|
||||
},
|
||||
|
||||
@@ -446,7 +446,7 @@ function rewriteAssistantToolCallIds(params: {
|
||||
return block;
|
||||
}
|
||||
changed = true;
|
||||
return { ...(block as unknown as Record<string, unknown>), id: nextId };
|
||||
return Object.assign({}, block as unknown as Record<string, unknown>, { id: nextId });
|
||||
});
|
||||
|
||||
if (!changed) {
|
||||
|
||||
@@ -364,15 +364,18 @@ export function parseAvailableTags(raw: unknown): AvailableTag[] | undefined {
|
||||
(t): t is Record<string, unknown> =>
|
||||
typeof t === "object" && t !== null && typeof t.name === "string",
|
||||
)
|
||||
.map((t) => ({
|
||||
...(t.id !== undefined && typeof t.id === "string" ? { id: t.id } : {}),
|
||||
name: t.name as string,
|
||||
...(typeof t.moderated === "boolean" ? { moderated: t.moderated } : {}),
|
||||
...(t.emoji_id === null || typeof t.emoji_id === "string" ? { emoji_id: t.emoji_id } : {}),
|
||||
...(t.emoji_name === null || typeof t.emoji_name === "string"
|
||||
? { emoji_name: t.emoji_name }
|
||||
: {}),
|
||||
}));
|
||||
.map((t) =>
|
||||
Object.assign(
|
||||
{},
|
||||
t.id !== undefined && typeof t.id === `string` ? { id: t.id } : {},
|
||||
{ name: t.name as string },
|
||||
typeof t.moderated === `boolean` ? { moderated: t.moderated } : {},
|
||||
t.emoji_id === null || typeof t.emoji_id === `string` ? { emoji_id: t.emoji_id } : {},
|
||||
t.emoji_name === null || typeof t.emoji_name === `string`
|
||||
? { emoji_name: t.emoji_name }
|
||||
: {},
|
||||
),
|
||||
);
|
||||
// Return undefined instead of empty array to avoid accidentally clearing all tags
|
||||
return result.length ? result : undefined;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,9 @@ export async function resolveAcpAttachments(params: {
|
||||
const mediaAttachments = runtime
|
||||
.normalizeAttachments(params.ctx)
|
||||
.map((attachment) =>
|
||||
normalizeOptionalString(attachment.path) ? { ...attachment, url: undefined } : attachment,
|
||||
normalizeOptionalString(attachment.path)
|
||||
? Object.assign({}, attachment, { url: undefined })
|
||||
: attachment,
|
||||
);
|
||||
const cache = new runtime.MediaAttachmentCache(mediaAttachments, {
|
||||
localPathRoots: runtime.resolveMediaAttachmentLocalRoots({
|
||||
|
||||
@@ -57,11 +57,10 @@ export function filterMessagingToolMediaDuplicates(params: {
|
||||
if (!stripSingle && (!mediaUrls || filteredUrls?.length === mediaUrls.length)) {
|
||||
return payload;
|
||||
}
|
||||
return {
|
||||
...payload,
|
||||
return Object.assign({}, payload, {
|
||||
mediaUrl: stripSingle ? undefined : mediaUrl,
|
||||
mediaUrls: filteredUrls?.length ? filteredUrls : undefined,
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ function resolveProviderChoiceOptions(params?: {
|
||||
scope: "text-inference",
|
||||
}).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
|
||||
@@ -140,10 +141,9 @@ export function buildAuthChoiceGroups(params: {
|
||||
});
|
||||
}
|
||||
const groups = Array.from(groupsById.values())
|
||||
.map((group) => ({
|
||||
...group,
|
||||
options: [...group.options].toSorted(compareAssistantOptions),
|
||||
}))
|
||||
.map((group) =>
|
||||
Object.assign({}, group, { options: [...group.options].toSorted(compareAssistantOptions) }),
|
||||
)
|
||||
.toSorted(compareGroupLabels);
|
||||
|
||||
const skipOption = params.includeSkip
|
||||
|
||||
@@ -160,13 +160,12 @@ export async function resolveBackupPlanFromPaths(params: {
|
||||
const candidates: BackupAssetCandidate[] = await Promise.all(
|
||||
rawCandidates.map(async (candidate) => {
|
||||
const exists = await pathExists(candidate.sourcePath);
|
||||
return {
|
||||
...candidate,
|
||||
return Object.assign({}, candidate, {
|
||||
exists,
|
||||
canonicalPath: exists
|
||||
? await canonicalizeExistingPath(candidate.sourcePath)
|
||||
: path.resolve(candidate.sourcePath),
|
||||
};
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -97,13 +97,11 @@ export function resolveChannelSetupEntries(params: {
|
||||
manifestInstalledIds.has(entry.id as ChannelChoice) &&
|
||||
shouldShowChannelInSetup(entry.meta),
|
||||
)
|
||||
.map((entry) => ({
|
||||
...entry,
|
||||
meta: normalizeChannelMeta({
|
||||
id: entry.id as ChannelChoice,
|
||||
meta: entry.meta,
|
||||
.map((entry) =>
|
||||
Object.assign({}, entry, {
|
||||
meta: normalizeChannelMeta({ id: entry.id as ChannelChoice, meta: entry.meta }),
|
||||
}),
|
||||
}));
|
||||
);
|
||||
const installableCatalogEntries = installableCatalogEntriesSource
|
||||
.filter(
|
||||
(entry) =>
|
||||
@@ -111,13 +109,11 @@ export function resolveChannelSetupEntries(params: {
|
||||
!manifestInstalledIds.has(entry.id as ChannelChoice) &&
|
||||
shouldShowChannelInSetup(entry.meta),
|
||||
)
|
||||
.map((entry) => ({
|
||||
...entry,
|
||||
meta: normalizeChannelMeta({
|
||||
id: entry.id as ChannelChoice,
|
||||
meta: entry.meta,
|
||||
.map((entry) =>
|
||||
Object.assign({}, entry, {
|
||||
meta: normalizeChannelMeta({ id: entry.id as ChannelChoice, meta: entry.meta }),
|
||||
}),
|
||||
}));
|
||||
);
|
||||
|
||||
const metaById = new Map<string, ChannelMeta>();
|
||||
for (const meta of listChatChannels()) {
|
||||
|
||||
@@ -185,13 +185,14 @@ export async function maybeRepairBundledPluginRuntimeDeps(params: {
|
||||
|
||||
const { missing, conflicts } = scanBundledPluginRuntimeDeps({ packageRoot });
|
||||
if (conflicts.length > 0) {
|
||||
const conflictLines = conflicts.flatMap((conflict) => [
|
||||
`- ${conflict.name}: ${conflict.versions.join(", ")}`,
|
||||
...conflict.versions.flatMap((version) => {
|
||||
const pluginIds = conflict.pluginIdsByVersion.get(version) ?? [];
|
||||
return pluginIds.length > 0 ? [` - ${version}: ${pluginIds.join(", ")}`] : [];
|
||||
}),
|
||||
]);
|
||||
const conflictLines = conflicts.flatMap((conflict) =>
|
||||
[`- ${conflict.name}: ${conflict.versions.join(", ")}`].concat(
|
||||
conflict.versions.flatMap((version) => {
|
||||
const pluginIds = conflict.pluginIdsByVersion.get(version) ?? [];
|
||||
return pluginIds.length > 0 ? [` - ${version}: ${pluginIds.join(", ")}`] : [];
|
||||
}),
|
||||
),
|
||||
);
|
||||
note(
|
||||
[
|
||||
"Bundled plugin runtime deps use conflicting versions.",
|
||||
|
||||
@@ -531,10 +531,7 @@ export function normalizeLegacyMistralModelMaxTokens(
|
||||
changes.push(
|
||||
`Normalized models.providers.${providerId}.models[${index}].maxTokens (${maxTokens} → ${normalizedMaxTokens}) to avoid Mistral context-window rejects.`,
|
||||
);
|
||||
return {
|
||||
...model,
|
||||
maxTokens: normalizedMaxTokens,
|
||||
};
|
||||
return Object.assign({}, model, { maxTokens: normalizedMaxTokens });
|
||||
});
|
||||
|
||||
if (!modelsChanged) {
|
||||
|
||||
@@ -123,16 +123,17 @@ function buildActionRows(params: {
|
||||
cappedKeys: Set<string>;
|
||||
budgetEvictedKeys: Set<string>;
|
||||
}): SessionCleanupActionRow[] {
|
||||
return toSessionDisplayRows(params.beforeStore).map((row) => ({
|
||||
...row,
|
||||
action: resolveSessionCleanupAction({
|
||||
key: row.key,
|
||||
missingKeys: params.missingKeys,
|
||||
staleKeys: params.staleKeys,
|
||||
cappedKeys: params.cappedKeys,
|
||||
budgetEvictedKeys: params.budgetEvictedKeys,
|
||||
return toSessionDisplayRows(params.beforeStore).map((row) =>
|
||||
Object.assign({}, row, {
|
||||
action: resolveSessionCleanupAction({
|
||||
key: row.key,
|
||||
missingKeys: params.missingKeys,
|
||||
staleKeys: params.staleKeys,
|
||||
cappedKeys: params.cappedKeys,
|
||||
budgetEvictedKeys: params.budgetEvictedKeys,
|
||||
}),
|
||||
}),
|
||||
}));
|
||||
);
|
||||
}
|
||||
|
||||
function pruneMissingTranscriptEntries(params: {
|
||||
|
||||
@@ -146,11 +146,12 @@ export async function sessionsCommand(
|
||||
const rows = targets
|
||||
.flatMap((target) => {
|
||||
const store = loadSessionStore(target.storePath);
|
||||
return toSessionDisplayRows(store).map((row) => ({
|
||||
...row,
|
||||
agentId: parseAgentSessionKey(row.key)?.agentId ?? target.agentId,
|
||||
kind: classifySessionKey(row.key, store[row.key]),
|
||||
}));
|
||||
return toSessionDisplayRows(store).map((row) =>
|
||||
Object.assign({}, row, {
|
||||
agentId: parseAgentSessionKey(row.key)?.agentId ?? target.agentId,
|
||||
kind: classifySessionKey(row.key, store[row.key]),
|
||||
}),
|
||||
);
|
||||
})
|
||||
.filter((row) => {
|
||||
if (activeMinutes === undefined) {
|
||||
|
||||
@@ -51,7 +51,7 @@ export function buildStatusChannelsSection(params: {
|
||||
width: params.width,
|
||||
renderTable: params.renderTable,
|
||||
columns: statusChannelsTableColumns.map((column) =>
|
||||
column.key === "Detail" ? { ...column, minWidth: 28 } : column,
|
||||
column.key === "Detail" ? Object.assign({}, column, { minWidth: 28 }) : column,
|
||||
),
|
||||
rows: buildStatusChannelsTableRows({
|
||||
rows: params.rows,
|
||||
|
||||
@@ -264,11 +264,11 @@ async function createMockStatusScanResult(params: { includePluginCompatibility?:
|
||||
...mocks.listGatewayAgentsBasic(),
|
||||
bootstrapPendingCount: 0,
|
||||
totalSessions: 1,
|
||||
agents: mocks.listGatewayAgentsBasic().agents.map((agent: { id: string; name?: string }) => ({
|
||||
...agent,
|
||||
bootstrapPending: false,
|
||||
activeSessions: 1,
|
||||
})),
|
||||
agents: mocks
|
||||
.listGatewayAgentsBasic()
|
||||
.agents.map((agent: { id: string; name?: string }) =>
|
||||
Object.assign({}, agent, { bootstrapPending: false, activeSessions: 1 }),
|
||||
),
|
||||
};
|
||||
const sessions = createSessionStatusRows();
|
||||
const channelIssues = gatewayReachable
|
||||
|
||||
@@ -211,15 +211,14 @@ export function applyModelDefaults(cfg: OpenClawConfig): OpenClawConfig {
|
||||
return model;
|
||||
}
|
||||
providerMutated = true;
|
||||
return {
|
||||
...raw,
|
||||
return Object.assign({}, raw, {
|
||||
reasoning,
|
||||
input,
|
||||
cost,
|
||||
contextWindow,
|
||||
maxTokens,
|
||||
api,
|
||||
} as ModelDefinitionConfig;
|
||||
}) as ModelDefinitionConfig;
|
||||
});
|
||||
|
||||
if (!providerMutated) {
|
||||
|
||||
@@ -248,7 +248,9 @@ export async function resolveAllAgentSessionStoreTargets(
|
||||
agentsRoot,
|
||||
realAgentsRoot,
|
||||
});
|
||||
return validatedStorePath ? { ...target, storePath: validatedStorePath } : undefined;
|
||||
return validatedStorePath
|
||||
? Object.assign({}, target, { storePath: validatedStorePath })
|
||||
: undefined;
|
||||
}),
|
||||
)
|
||||
).filter((target): target is SessionStoreTarget => Boolean(target));
|
||||
|
||||
@@ -514,10 +514,9 @@ export async function dispatchCronDelivery(
|
||||
return p;
|
||||
}
|
||||
const normalized = normalizeSilentReplyText(p.text);
|
||||
return {
|
||||
...p,
|
||||
return Object.assign({}, p, {
|
||||
text: normalized.strippedTrailingSilentToken ? undefined : normalized.text,
|
||||
};
|
||||
});
|
||||
})
|
||||
.filter((p) => hasReplyPayloadContent(p, { trimText: true }));
|
||||
if (payloadsForDelivery.length === 0) {
|
||||
|
||||
@@ -118,41 +118,47 @@ function listReloadRules(): ReloadRule[] {
|
||||
return cachedReloadRules;
|
||||
}
|
||||
// Channel docking: plugins contribute hot reload/no-op prefixes here.
|
||||
const channelReloadRules: ReloadRule[] = listChannelPlugins().flatMap((plugin) => [
|
||||
...(plugin.reload?.configPrefixes ?? []).map(
|
||||
(prefix): ReloadRule => ({
|
||||
prefix,
|
||||
kind: "hot",
|
||||
actions: [`restart-channel:${plugin.id}` as ReloadAction],
|
||||
}),
|
||||
),
|
||||
...(plugin.reload?.noopPrefixes ?? []).map(
|
||||
(prefix): ReloadRule => ({
|
||||
prefix,
|
||||
kind: "none",
|
||||
}),
|
||||
),
|
||||
]);
|
||||
const pluginReloadRules: ReloadRule[] = (registry?.reloads ?? []).flatMap((entry) => [
|
||||
...(entry.registration.restartPrefixes ?? []).map(
|
||||
(prefix): ReloadRule => ({
|
||||
prefix,
|
||||
kind: "restart",
|
||||
}),
|
||||
),
|
||||
...(entry.registration.hotPrefixes ?? []).map(
|
||||
(prefix): ReloadRule => ({
|
||||
prefix,
|
||||
kind: "hot",
|
||||
}),
|
||||
),
|
||||
...(entry.registration.noopPrefixes ?? []).map(
|
||||
(prefix): ReloadRule => ({
|
||||
prefix,
|
||||
kind: "none",
|
||||
}),
|
||||
),
|
||||
]);
|
||||
const channelReloadRules: ReloadRule[] = listChannelPlugins().flatMap((plugin) =>
|
||||
(plugin.reload?.configPrefixes ?? [])
|
||||
.map(
|
||||
(prefix): ReloadRule => ({
|
||||
prefix,
|
||||
kind: "hot",
|
||||
actions: [`restart-channel:${plugin.id}` as ReloadAction],
|
||||
}),
|
||||
)
|
||||
.concat(
|
||||
(plugin.reload?.noopPrefixes ?? []).map(
|
||||
(prefix): ReloadRule => ({
|
||||
prefix,
|
||||
kind: "none",
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
const pluginReloadRules: ReloadRule[] = (registry?.reloads ?? []).flatMap((entry) =>
|
||||
(entry.registration.restartPrefixes ?? [])
|
||||
.map(
|
||||
(prefix): ReloadRule => ({
|
||||
prefix,
|
||||
kind: "restart",
|
||||
}),
|
||||
)
|
||||
.concat(
|
||||
(entry.registration.hotPrefixes ?? []).map(
|
||||
(prefix): ReloadRule => ({
|
||||
prefix,
|
||||
kind: "hot",
|
||||
}),
|
||||
),
|
||||
(entry.registration.noopPrefixes ?? []).map(
|
||||
(prefix): ReloadRule => ({
|
||||
prefix,
|
||||
kind: "none",
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
const rules = [
|
||||
...BASE_RELOAD_RULES,
|
||||
...pluginReloadRules,
|
||||
|
||||
@@ -1213,10 +1213,9 @@ function buildLiveGatewayConfig(params: {
|
||||
...params.cfg,
|
||||
agents: {
|
||||
...params.cfg.agents,
|
||||
list: (params.cfg.agents?.list ?? []).map((entry) => ({
|
||||
...entry,
|
||||
sandbox: { mode: "off" },
|
||||
})),
|
||||
list: (params.cfg.agents?.list ?? []).map((entry) =>
|
||||
Object.assign({}, entry, { sandbox: { mode: `off` } }),
|
||||
),
|
||||
defaults: {
|
||||
...params.cfg.agents?.defaults,
|
||||
// Live tests should avoid Docker sandboxing so tool probes can
|
||||
|
||||
@@ -221,7 +221,9 @@ type MockConfig = {
|
||||
};
|
||||
|
||||
function getAgentList(cfg: unknown): MockAgentEntry[] {
|
||||
return ((cfg as MockConfig | undefined)?.agents?.list ?? []).map((entry) => ({ ...entry }));
|
||||
return ((cfg as MockConfig | undefined)?.agents?.list ?? []).map((entry) =>
|
||||
Object.assign({}, entry),
|
||||
);
|
||||
}
|
||||
|
||||
function mergeAgentConfig(cfg: unknown, opts: unknown): MockConfig {
|
||||
|
||||
@@ -120,10 +120,9 @@ function buildPluginGroups(params: {
|
||||
groups.set(groupId, existing);
|
||||
}
|
||||
return [...groups.values()]
|
||||
.map((group) => ({
|
||||
...group,
|
||||
tools: group.tools.toSorted((a, b) => a.id.localeCompare(b.id)),
|
||||
}))
|
||||
.map((group) =>
|
||||
Object.assign({}, group, { tools: group.tools.toSorted((a, b) => a.id.localeCompare(b.id)) }),
|
||||
)
|
||||
.toSorted((a, b) => a.label.localeCompare(b.label));
|
||||
}
|
||||
|
||||
|
||||
@@ -293,7 +293,7 @@ async function discoverAllSessionsForUsage(params: {
|
||||
startMs: params.startMs,
|
||||
endMs: params.endMs,
|
||||
});
|
||||
return sessions.map((session) => ({ ...session, agentId: agent.id }));
|
||||
return sessions.map((session) => Object.assign({}, session, { agentId: agent.id }));
|
||||
}),
|
||||
);
|
||||
return results.flat().toSorted((a, b) => b.mtime - a.mtime);
|
||||
|
||||
@@ -574,10 +574,7 @@ async function discoverViaAvahi(
|
||||
args.push("-d", domain.replace(/\.$/, ""));
|
||||
}
|
||||
const browse = await run(args, { timeoutMs });
|
||||
return parseAvahiBrowse(browse.stdout).map((beacon) => ({
|
||||
...beacon,
|
||||
domain,
|
||||
}));
|
||||
return parseAvahiBrowse(browse.stdout).map((beacon) => Object.assign({}, beacon, { domain }));
|
||||
}
|
||||
|
||||
export async function discoverGatewayBeacons(
|
||||
|
||||
@@ -854,13 +854,12 @@ export function recordAllowlistUse(
|
||||
const nextAllowlist = allowlist.map((item) =>
|
||||
item.pattern === entry.pattern &&
|
||||
(item.argPattern ?? undefined) === (entry.argPattern ?? undefined)
|
||||
? {
|
||||
...item,
|
||||
? Object.assign({}, item, {
|
||||
id: item.id ?? crypto.randomUUID(),
|
||||
lastUsedAt: Date.now(),
|
||||
lastUsedCommand: command,
|
||||
lastResolvedPath: resolvedPath,
|
||||
}
|
||||
})
|
||||
: item,
|
||||
);
|
||||
agents[target] = { ...existing, allowlist: nextAllowlist };
|
||||
|
||||
@@ -967,10 +967,11 @@ export function markdownToIRWithMeta(
|
||||
links: clampLinkSpans(state.links, finalLength),
|
||||
},
|
||||
hasTables: state.hasTables,
|
||||
tables: state.collectedTables.map((table) => ({
|
||||
...table,
|
||||
placeholderOffset: Math.min(table.placeholderOffset, finalLength),
|
||||
})),
|
||||
tables: state.collectedTables.map((table) =>
|
||||
Object.assign({}, table, {
|
||||
placeholderOffset: Math.min(table.placeholderOffset, finalLength),
|
||||
}),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -341,11 +341,9 @@ describe("pairing store", () => {
|
||||
requests?: Array<Record<string, unknown>>;
|
||||
};
|
||||
const expiredAt = new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString();
|
||||
const requests = (parsed.requests ?? []).map((entry) => ({
|
||||
...entry,
|
||||
createdAt: expiredAt,
|
||||
lastSeenAt: expiredAt,
|
||||
}));
|
||||
const requests = (parsed.requests ?? []).map((entry) =>
|
||||
Object.assign({}, entry, { createdAt: expiredAt, lastSeenAt: expiredAt }),
|
||||
);
|
||||
await writeJsonFixture(filePath, { version: 1, requests });
|
||||
expect(await listChannelPairingRequests("demo-pairing-b")).toHaveLength(0);
|
||||
const next = await upsertChannelPairingRequest({
|
||||
|
||||
@@ -28,8 +28,7 @@ function loadPluginRuntime(): PluginRuntimeModule | null {
|
||||
}
|
||||
|
||||
export function resolveRuntimeCliBackends(): PluginCliBackendEntry[] {
|
||||
return (loadPluginRuntime()?.getActivePluginRegistry()?.cliBackends ?? []).map((entry) => ({
|
||||
...entry.backend,
|
||||
pluginId: entry.pluginId,
|
||||
}));
|
||||
return (loadPluginRuntime()?.getActivePluginRegistry()?.cliBackends ?? []).map((entry) =>
|
||||
Object.assign({}, entry.backend, { pluginId: entry.pluginId }),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2822,12 +2822,13 @@ module.exports = { id: "throws-after-import", register() {} };`,
|
||||
] as const;
|
||||
|
||||
runSinglePluginRegistryScenarios(
|
||||
scenarios.map((scenario) => ({
|
||||
...scenario,
|
||||
body: `module.exports = { id: "${scenario.pluginId}", register(api) {
|
||||
scenarios.map((scenario) =>
|
||||
Object.assign({}, scenario, {
|
||||
body: `module.exports = { id: "${scenario.pluginId}", register(api) {
|
||||
api.registerHttpRoute(${scenario.routeOptions});
|
||||
} };`,
|
||||
})),
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -57,10 +57,9 @@ function resolveProviderDiscoveryEntryPlugins(params: {
|
||||
try {
|
||||
const moduleExport = loadSource(manifest.providerDiscoverySource!) as ProviderDiscoveryModule;
|
||||
providers.push(
|
||||
...normalizeDiscoveryModule(moduleExport).map((provider) => ({
|
||||
...provider,
|
||||
pluginId: manifest.id,
|
||||
})),
|
||||
...normalizeDiscoveryModule(moduleExport).map((provider) =>
|
||||
Object.assign({}, provider, { pluginId: manifest.id }),
|
||||
),
|
||||
);
|
||||
} catch {
|
||||
// Discovery fast path is optional. Fall back to the full plugin loader
|
||||
|
||||
@@ -275,10 +275,9 @@ export function resolvePluginProviders(params: {
|
||||
return [];
|
||||
}
|
||||
const registry = loadOpenClawPlugins(loadState.loadOptions);
|
||||
return registry.providers.map((entry) => ({
|
||||
...entry.provider,
|
||||
pluginId: entry.pluginId,
|
||||
}));
|
||||
return registry.providers.map((entry) =>
|
||||
Object.assign({}, entry.provider, { pluginId: entry.pluginId }),
|
||||
);
|
||||
}
|
||||
const loadState = resolveRuntimeProviderPluginLoadState(params, base);
|
||||
const registry = resolveRuntimePluginRegistry(loadState.loadOptions);
|
||||
@@ -286,8 +285,7 @@ export function resolvePluginProviders(params: {
|
||||
return [];
|
||||
}
|
||||
|
||||
return registry.providers.map((entry) => ({
|
||||
...entry.provider,
|
||||
pluginId: entry.pluginId,
|
||||
}));
|
||||
return registry.providers.map((entry) =>
|
||||
Object.assign({}, entry.provider, { pluginId: entry.pluginId }),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,29 +19,38 @@ const LIVE_RUNTIME_STATE_GUARDS: Record<
|
||||
},
|
||||
};
|
||||
|
||||
function guardAssertions() {
|
||||
return Object.entries(LIVE_RUNTIME_STATE_GUARDS).flatMap(([relativePath, guard]) => [
|
||||
...guard.required.map((needle) => ({
|
||||
relativePath,
|
||||
type: "required" as const,
|
||||
needle,
|
||||
message: `${relativePath} missing ${needle}`,
|
||||
})),
|
||||
...guard.forbidden.map((needle) => ({
|
||||
relativePath,
|
||||
type: "forbidden" as const,
|
||||
needle,
|
||||
message: `${relativePath} must not contain ${needle}`,
|
||||
})),
|
||||
]);
|
||||
}
|
||||
|
||||
function expectGuardState(params: {
|
||||
source: string;
|
||||
type GuardAssertion = {
|
||||
relativePath: string;
|
||||
type: "required" | "forbidden";
|
||||
needle: string;
|
||||
message: string;
|
||||
}) {
|
||||
};
|
||||
|
||||
function guardAssertions(): GuardAssertion[] {
|
||||
return Object.entries(LIVE_RUNTIME_STATE_GUARDS).flatMap(([relativePath, guard]) =>
|
||||
guard.required
|
||||
.map<GuardAssertion>((needle) => ({
|
||||
relativePath,
|
||||
type: "required",
|
||||
needle,
|
||||
message: `${relativePath} missing ${needle}`,
|
||||
}))
|
||||
.concat(
|
||||
guard.forbidden.map<GuardAssertion>((needle) => ({
|
||||
relativePath,
|
||||
type: "forbidden",
|
||||
needle,
|
||||
message: `${relativePath} must not contain ${needle}`,
|
||||
})),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function expectGuardState(
|
||||
params: {
|
||||
source: string;
|
||||
} & Pick<GuardAssertion, "message" | "needle" | "type">,
|
||||
) {
|
||||
if (params.type === "required") {
|
||||
expect(params.source, params.message).toContain(params.needle);
|
||||
return;
|
||||
|
||||
@@ -208,11 +208,12 @@ function buildPluginReport(
|
||||
return {
|
||||
workspaceDir,
|
||||
...registry,
|
||||
plugins: registry.plugins.map((plugin) => ({
|
||||
...plugin,
|
||||
imported: plugin.format !== "bundle" && importedPluginIds.has(plugin.id),
|
||||
version: resolveReportedPluginVersion(plugin, params?.env),
|
||||
})),
|
||||
plugins: registry.plugins.map((plugin) =>
|
||||
Object.assign({}, plugin, {
|
||||
imported: plugin.format !== `bundle` && importedPluginIds.has(plugin.id),
|
||||
version: resolveReportedPluginVersion(plugin, params?.env),
|
||||
}),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ export function loadBundledWebSearchProviderEntriesFromDir(params: {
|
||||
if (providers.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return providers.map((provider) => ({ ...provider, pluginId: params.pluginId }));
|
||||
return providers.map((provider) => Object.assign({}, provider, { pluginId: params.pluginId }));
|
||||
}
|
||||
|
||||
export function loadBundledRuntimeWebSearchProviderEntriesFromDir(params: {
|
||||
@@ -148,7 +148,7 @@ export function loadBundledRuntimeWebSearchProviderEntriesFromDir(params: {
|
||||
if (providers.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return providers.map((provider) => ({ ...provider, pluginId: params.pluginId }));
|
||||
return providers.map((provider) => Object.assign({}, provider, { pluginId: params.pluginId }));
|
||||
}
|
||||
|
||||
export function loadBundledWebFetchProviderEntriesFromDir(params: {
|
||||
@@ -170,7 +170,7 @@ export function loadBundledWebFetchProviderEntriesFromDir(params: {
|
||||
if (providers.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return providers.map((provider) => ({ ...provider, pluginId: params.pluginId }));
|
||||
return providers.map((provider) => Object.assign({}, provider, { pluginId: params.pluginId }));
|
||||
}
|
||||
|
||||
export function resolveBundledExplicitWebSearchProvidersFromPublicArtifacts(params: {
|
||||
|
||||
@@ -175,9 +175,6 @@ export function mapRegistryProviders<TProvider extends { id: string }>(params: {
|
||||
return params.sortProviders(
|
||||
params.entries
|
||||
.filter((entry) => !onlyPluginIdSet || onlyPluginIdSet.has(entry.pluginId))
|
||||
.map((entry) => ({
|
||||
...entry.provider,
|
||||
pluginId: entry.pluginId,
|
||||
})),
|
||||
.map((entry) => Object.assign({}, entry.provider, { pluginId: entry.pluginId })),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ export function createRunRegistry(options?: { maxExitedRecords?: number }): RunR
|
||||
};
|
||||
|
||||
const list: RunRegistry["list"] = () => {
|
||||
return Array.from(records.values()).map((record) => ({ ...record }));
|
||||
return Array.from(records.values()).map((record) => Object.assign({}, record));
|
||||
};
|
||||
|
||||
const listByScope: RunRegistry["listByScope"] = (scopeKey) => {
|
||||
@@ -84,7 +84,7 @@ export function createRunRegistry(options?: { maxExitedRecords?: number }): RunR
|
||||
}
|
||||
return Array.from(records.values())
|
||||
.filter((record) => record.scopeKey === scopeKey)
|
||||
.map((record) => ({ ...record }));
|
||||
.map((record) => Object.assign({}, record));
|
||||
};
|
||||
|
||||
const updateState: RunRegistry["updateState"] = (runId, state, patch) => {
|
||||
|
||||
@@ -1814,7 +1814,7 @@ export async function cancelTaskById(params: {
|
||||
export function listTaskRecords(): TaskRecord[] {
|
||||
ensureTaskRegistryReady();
|
||||
return [...tasks.values()]
|
||||
.map((task, insertionIndex) => ({ ...cloneTaskRecord(task), insertionIndex }))
|
||||
.map((task, insertionIndex) => Object.assign({}, cloneTaskRecord(task), { insertionIndex }))
|
||||
.toSorted(compareTasksNewestFirst)
|
||||
.map(({ insertionIndex: _, ...task }) => task);
|
||||
}
|
||||
@@ -1851,7 +1851,7 @@ function listTasksFromIndex(index: Map<string, Set<string>>, key: string): TaskR
|
||||
return [...ids]
|
||||
.map((taskId, insertionIndex) => {
|
||||
const task = tasks.get(taskId);
|
||||
return task ? { ...cloneTaskRecord(task), insertionIndex } : null;
|
||||
return task ? Object.assign({}, cloneTaskRecord(task), { insertionIndex }) : null;
|
||||
})
|
||||
.filter(
|
||||
(
|
||||
|
||||
@@ -155,7 +155,7 @@ function buildToolRichSystemPrompt(params: {
|
||||
"web_search",
|
||||
"x_search",
|
||||
"web_fetch",
|
||||
].map((name) => ({ ...createStubTool(name), description: `${name} tool` }));
|
||||
].map((name) => Object.assign({}, createStubTool(name), { description: `${name} tool` }));
|
||||
return buildEmbeddedSystemPrompt({
|
||||
workspaceDir: params.workspaceDir,
|
||||
reasoningTagHint: false,
|
||||
|
||||
@@ -211,13 +211,7 @@ function expandTextContent(text: string): {
|
||||
const content = mergeAdjacentTextItems(
|
||||
parts.map((item) => {
|
||||
if (item.type === "attachment" && item.attachment.kind === "audio" && audioAsVoice) {
|
||||
return {
|
||||
...item,
|
||||
attachment: {
|
||||
...item.attachment,
|
||||
isVoiceNote: true,
|
||||
},
|
||||
};
|
||||
return Object.assign({}, item, { attachment: { ...item.attachment, isVoiceNote: true } });
|
||||
}
|
||||
return item;
|
||||
}),
|
||||
|
||||
@@ -276,12 +276,7 @@ function patchSessionThinkingLevel(
|
||||
state.sessionsResult = {
|
||||
...current,
|
||||
sessions: current.sessions.map((row) =>
|
||||
row.key === sessionKey
|
||||
? {
|
||||
...row,
|
||||
thinkingLevel,
|
||||
}
|
||||
: row,
|
||||
row.key === sessionKey ? Object.assign({}, row, { thinkingLevel }) : row,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -724,12 +724,13 @@ export function renderConfig(props: ConfigProps) {
|
||||
const schemaProps = analysis.schema?.properties ?? {};
|
||||
|
||||
const VIRTUAL_SECTIONS = new Set(["__appearance__"]);
|
||||
const visibleCategories = SECTION_CATEGORIES.map((cat) => ({
|
||||
...cat,
|
||||
sections: cat.sections.filter(
|
||||
(s) => (includeVirtualSections && VIRTUAL_SECTIONS.has(s.key)) || s.key in schemaProps,
|
||||
),
|
||||
})).filter((cat) => cat.sections.length > 0);
|
||||
const visibleCategories = SECTION_CATEGORIES.map((cat) =>
|
||||
Object.assign({}, cat, {
|
||||
sections: cat.sections.filter(
|
||||
(s) => (includeVirtualSections && VIRTUAL_SECTIONS.has(s.key)) || s.key in schemaProps,
|
||||
),
|
||||
}),
|
||||
).filter((cat) => cat.sections.length > 0);
|
||||
|
||||
// Catch any schema keys not in our categories
|
||||
const extraSections = Object.keys(schemaProps)
|
||||
|
||||
@@ -80,10 +80,7 @@ function formatDiaryChipLabel(date: string): string {
|
||||
|
||||
function buildDiaryNavigation(entries: DiaryEntry[]): DiaryEntryNav[] {
|
||||
const reversed = [...entries].toReversed();
|
||||
return reversed.map((entry, page) => ({
|
||||
...entry,
|
||||
page,
|
||||
}));
|
||||
return reversed.map((entry, page) => Object.assign({}, entry, { page }));
|
||||
}
|
||||
|
||||
type DreamingPhaseInfo = {
|
||||
|
||||
Reference in New Issue
Block a user