From 9a77054e2fc4b13f0ff4f2e1feca9fcdb8910b2c Mon Sep 17 00:00:00 2001 From: luoye520ww <100058663+luoye520ww@users.noreply.github.com> Date: Mon, 13 Jul 2026 21:53:26 +0800 Subject: [PATCH 1/2] fix(config): preserve valid fields during section sanitization --- src/main/kun-process.test.ts | 2 + .../runtime/kun-runtime-config-service.ts | 44 ++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/main/kun-process.test.ts b/src/main/kun-process.test.ts index 0eb1c39b5..4192fabb1 100644 --- a/src/main/kun-process.test.ts +++ b/src/main/kun-process.test.ts @@ -1160,6 +1160,7 @@ describe('syncGuiManagedKunConfig', () => { } }, serve: { + runtimeToken: 'keep-this-token', legacyServeFlag: true, tokenEconomy: { customTokenEconomyFlag: 'keep', @@ -1248,6 +1249,7 @@ describe('syncGuiManagedKunConfig', () => { expect(KunConfigSchema.safeParse(parsed).success).toBe(true) expect(parsed.legacyTopLevelFlag).toBeUndefined() expect(parsed.serve.legacyServeFlag).toBeUndefined() + expect(parsed.serve.runtimeToken).toBe('keep-this-token') expect(parsed.serve.storage).toMatchObject({ backend: 'hybrid', sqlitePath: '/tmp/kun-index.sqlite3' diff --git a/src/main/runtime/kun-runtime-config-service.ts b/src/main/runtime/kun-runtime-config-service.ts index 0d1b64157..1caae34b2 100644 --- a/src/main/runtime/kun-runtime-config-service.ts +++ b/src/main/runtime/kun-runtime-config-service.ts @@ -311,8 +311,48 @@ function sanitizeCapabilities(value: unknown): Record { } function parseKunConfigSection(schema: SafeParseSchema, value: unknown): Record { - const parsed = schema.safeParse(objectValue(value)) - return parsed.success ? objectValue(parsed.data) : {} + const raw = objectValue(value) + const parsed = schema.safeParse(raw) + if (parsed.success) return objectValue(parsed.data) + + // Older GUI/runtime versions may leave a newly introduced top-level key in + // the config. A strict schema should reject that key, but dropping the + // entire section also discards valid credentials and endpoint settings. + // Retry with only keys known by the object schema; invalid known values are + // still rejected by the normal schema and therefore fail closed. + const shape = schemaShape(schema) + if (!shape) return {} + const known = Object.fromEntries(Object.keys(shape).flatMap((key) => + key in raw ? [[key, raw[key]] as const] : [] + )) + const sanitized = schema.safeParse(known) + if (sanitized.success) return objectValue(sanitized.data) + + // A known nested object may itself contain an obsolete key. Validate each + // top-level value independently so one stale nested option cannot discard + // unrelated credentials or endpoint fields from the section. + const validEntries = Object.entries(known).flatMap(([key, entry]) => { + const parsedEntry = schema.safeParse({ [key]: entry }) + return parsedEntry.success ? [[key, objectValue(parsedEntry.data)[key]] as const] : [] + }) + return Object.fromEntries(validEntries) +} + +function schemaShape(schema: SafeParseSchema): Record | undefined { + const candidate = schema as SafeParseSchema & { + shape?: unknown + def?: unknown + _def?: unknown + } + for (const container of [candidate, candidate.def, candidate._def]) { + if (!container || typeof container !== 'object') continue + const rawShape = 'shape' in container ? (container as { shape?: unknown }).shape : undefined + const shape = typeof rawShape === 'function' ? rawShape() : rawShape + if (shape && typeof shape === 'object' && !Array.isArray(shape)) { + return shape as Record + } + } + return undefined } function parseKunHooksSection(value: unknown): unknown[] { From b7a002d8338b215d94e66e2c9627315f415e335b Mon Sep 17 00:00:00 2001 From: luoye520ww <100058663+luoye520ww@users.noreply.github.com> Date: Tue, 14 Jul 2026 22:09:06 +0800 Subject: [PATCH 2/2] fix(test): keep skill config imports Electron-free --- src/main/services/skill-service.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/services/skill-service.ts b/src/main/services/skill-service.ts index 660932bd9..7536af65a 100644 --- a/src/main/services/skill-service.ts +++ b/src/main/services/skill-service.ts @@ -8,7 +8,10 @@ import { COMMON_WORKSPACE_SKILL_DIRS, type CommonSkillDir } from '../../shared/skill-dirs' -import { expandHomePath } from './workspace-service' +// Keep the skill catalog usable from Node-only migration/config tests. The +// workspace barrel also exports Electron-backed editors and files, which +// unnecessarily requires the Electron binary during CI. +import { expandHomePath } from './workspace-paths' export type GuiSkillScope = 'project' | 'global'