Skip to content

fix(gateway): preserve config settings on startup and partial updates#162

Closed
ghost wants to merge 4 commits intomainfrom
unknown repository
Closed

fix(gateway): preserve config settings on startup and partial updates#162
ghost wants to merge 4 commits intomainfrom
unknown repository

Conversation

@ghost
Copy link

@ghost ghost commented Jan 3, 2026

Summary

Fixes a bug where recompiling the Mac gateway app caused all user configuration settings to be lost. After this fix, gateway settings persist across app rebuilds and partial config updates preserve existing fields.

Problem

Symptoms: When rebuilding the Mac app via swift build, users lost all gateway configuration (auth settings, provider tokens, custom ports, etc.).

Root Causes:

  1. Startup overwrite (src/gateway/server.ts:580): The gateway unconditionally called writeConfigFile(migrated) on every launch, overwriting existing user configuration with the migrated version.

  2. Partial update stripping (src/gateway/server.ts:1281, 3802): The config.set handler validated partial updates directly with Zod's ClawdisSchema. Since the schema lacked .passthrough() at the top level (only skills.entries had it), validating a partial config stripped away any fields not present in the update payload.

    Example: Updating only { agent: { model: "claude-3" } } would delete gateway.port, telegram.botToken, etc.

Solution

  1. Startup fix: Wrap the config write in if (!configSnapshot.exists) so migration only happens on first run. Existing config files are never overwritten at startup.

  2. Deep merge for partial updates: Added deepMergeConfig() helper that recursively merges nested objects while preserving existing fields. The config.set handler now merges the partial update with the existing config before validation.

Changes

src/gateway/server.ts

  1. New deepMergeConfig() function (lines 528-559): Recursively merges config objects, preserving nested structures. Arrays are replaced entirely (standard config behavior).

  2. Startup guard (lines 572-595): Only writes config on first run (!configSnapshot.exists). Logs a warning for legacy configs instead of overwriting.

  3. config.set merge fix: add @lid format support and allowFrom wildcard handling #1 (lines 1322-1329): Merges partial update with existing config before validation in the WebSocket-JSON handler.

  4. config.set merge Login fails with 'WebSocket Error (socket hang up)' ECONNRESET #2 (lines 3851-3858): Same merge logic in the WebSocket-response handler.

src/gateway/server-utils.test.ts (new file)

8 comprehensive tests covering:

  • Shallow object merging
  • Nested object deep merging
  • Array replacement behavior
  • Null/undefined handling
  • Empty objects
  • Full config.set partial update simulation

Test Plan

  • pnpm test --run server-utils.test.ts - 8 tests passed
  • pnpm build - TypeScript build succeeded
  • Manual: After merge, rebuild Mac app and confirm settings persist

Technical Details

Why not add .passthrough() to ClawdisSchema?

The schema is defined without .passthrough() intentionally to enforce strict validation. Adding it would allow arbitrary fields through, potentially masking misconfigurations. The deep merge approach preserves the existing strict validation while adding the missing preservation behavior.

Deep merge semantics:

  • Objects: Recursively merged (target overrides base)
  • Arrays: Replaced entirely (target array becomes the new array)
  • Primitives: Target value replaces base value
  • null/undefined: Handled per standard merge rules

Related Issues

This is the config preservation portion of the work from closed PRs #141, #142, #145, #146. Those PRs were monolithic (1000+ lines) and overlapped with other features. This is the minimal, atomic fix for just the config preservation issue.

Mind-Dragon and others added 4 commits January 3, 2026 12:31
Complete incomplete gateway module split by creating:
- server-utils.ts: formatError, normalizeVoiceWakeTriggers
- server-http.ts: HTTP server and hooks handlers
- server-providers.ts: provider manager for messaging services

Fix wizard/onboarding.ts using correct nextConfig variable.
Fix Swift 6 compiler crash in OnboardingWizard.swift by refactoring
complex view builders into smaller functions.
Fix AnyCodable type mismatches between Clawdis and ClawdisProtocol modules.
Add Sendable conformance to wizard result types.
Fix OnboardingView+Layout.swift with explicit return.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Fix gateway 30s timeout clamp causing frequent "Request was aborted" errors
- Increase chat.send timeout clamp from 30s to 10 minutes (600s)
- Set default bash command timeout to 10 minutes
- Fix TypeScript errors in discord/monitor.ts and gateway/call.ts

The gateway was capping all requests to 30s regardless of actual timeout,
causing agents to abort mid-execution for normal operations like file reads.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The gateway was overwriting user config on startup and stripping
existing fields during partial config updates.

## Root Cause
1. Startup logic unconditionally wrote migrated config on every launch
2. config.set validated partial updates directly, losing fields not in the update

## Solution
1. Startup: Only auto-migrate/write on first run (!configSnapshot.exists)
2. config.set: Deep merge new config with existing before validation
3. Exported deepMergeConfig() for testing

## Test Plan
- pnpm test --run server-utils.test.ts - 8 tests passed
- pnpm build - TypeScript build succeeded
@ghost
Copy link
Author

ghost commented Jan 3, 2026

Will recreate with proper base sync

@ghost ghost closed this Jan 3, 2026
slathrop referenced this pull request in slathrop/openclaw-js Feb 11, 2026
Tasks completed: 2/2
- Task 1: Port grammY fetch cast + spoiler tags (commits #34, #100)
- Task 2: Port command truncation to 100 limit (commits #161, #162)

SUMMARY: .planning/phases/14-telegram-channels/14-01-SUMMARY.md
songliu0403-rgb pushed a commit to songliu0403-rgb/openclaw that referenced this pull request Feb 26, 2026
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Haze <hazeone@users.noreply.github.com>
@joshprentice775
Copy link

✅ Phase 2 implementation COMPLETE. Auto-context injection feature implemented and tested.\n\nSummary:\n- Gateway hook injects vector search results into agent sessions at startup\n- Extracts current task from INBOX.md ## Now section\n- Calls SignalForge vector search API with task query\n- Formats results as AUTO_VECTOR_CONTEXT.md in system prompt\n- Configuration: agents.defaults.vectorContextInjection (enabled, minScore, maxResults, sourceTypes)\n\nFiles:\n- src/agents/vector-context-injection.ts (new)\n- src/agents/vector-context-injection.test.ts (new)\n- src/agents/pi-embedded-runner/run/attempt.ts (modified)\n- src/config/zod-schema.agent-defaults.ts (modified)\n\nTests: 4/4 passing ✅\nBuild: Successful ✅\n\nChain: #213#210 → ingestion → #162 ✅\n\nReady for review and merge.

cael-dandelion-cult added a commit to karmaterminal/openclaw that referenced this pull request Mar 4, 2026
karmafeast pushed a commit to karmaterminal/openclaw that referenced this pull request Mar 4, 2026
ronan-dandelion-cult pushed a commit to karmaterminal/openclaw that referenced this pull request Mar 4, 2026
…penclaw#162, openclaw#163)

- contextPressureThreshold (0.0-1.0) in continuation config block
- Zod validator: z.number().min(0).max(1).optional()
- lastContextPressureBand on session entry for dedup (fire once per band)
- Zero type errors in modified files

Unblocks openclaw#164 (injection) and openclaw#165 (tests).
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants