fix(gateway): preserve config settings on startup and partial updates#162
Conversation
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>
…essage bug on WhatsApp/Telegram surfaces
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
|
Will recreate with proper base sync |
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
Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Haze <hazeone@users.noreply.github.com>
|
✅ 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. |
…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).
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:
Startup overwrite (
src/gateway/server.ts:580): The gateway unconditionally calledwriteConfigFile(migrated)on every launch, overwriting existing user configuration with the migrated version.Partial update stripping (
src/gateway/server.ts:1281,3802): Theconfig.sethandler validated partial updates directly with Zod'sClawdisSchema. Since the schema lacked.passthrough()at the top level (onlyskills.entrieshad it), validating a partial config stripped away any fields not present in the update payload.Example: Updating only
{ agent: { model: "claude-3" } }would deletegateway.port,telegram.botToken, etc.Solution
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.Deep merge for partial updates: Added
deepMergeConfig()helper that recursively merges nested objects while preserving existing fields. Theconfig.sethandler now merges the partial update with the existing config before validation.Changes
src/gateway/server.tsNew
deepMergeConfig()function (lines 528-559): Recursively merges config objects, preserving nested structures. Arrays are replaced entirely (standard config behavior).Startup guard (lines 572-595): Only writes config on first run (
!configSnapshot.exists). Logs a warning for legacy configs instead of overwriting.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.
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:
Test Plan
pnpm test --run server-utils.test.ts- 8 tests passedpnpm build- TypeScript build succeededTechnical Details
Why not add
.passthrough()toClawdisSchema?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:
null/undefined: Handled per standard merge rulesRelated 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.