mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-20 09:17:51 +00:00
* fix: canonicalize session keys at write time to prevent orphaned sessions (#29683) resolveSessionKey() uses hardcoded DEFAULT_AGENT_ID="main", but all read paths canonicalize via cfg. When the configured default agent differs (e.g. "ops" with mainKey "work"), writes produce "agent:main:main" while reads look up "agent:ops:work", orphaning transcripts on every restart. Fix all three write-path call sites by wrapping with canonicalizeMainSessionAlias: - initSessionState (auto-reply/reply/session.ts) - runWebHeartbeatOnce (web/auto-reply/heartbeat-runner.ts) - resolveCronAgentSessionKey (cron/isolated-agent/session-key.ts) Add startup migration (migrateOrphanedSessionKeys) to rename existing orphaned keys to canonical form, merging by most-recent updatedAt. * fix: address review — track agent IDs in migration map, align snapshot key P1: migrateOrphanedSessionKeys now tracks agentId alongside each store path in a Map instead of inferring from the filesystem path. This correctly handles custom session.store templates outside the default agents/<id>/ layout. P2: Pass the already-canonicalized sessionKey to getSessionSnapshot so the heartbeat snapshot reads/restores use the same key as the write path. * fix: log migration results at all early return points migrateOrphanedSessionKeys runs before detectLegacyStateMigrations, so it can canonicalize legacy keys (e.g. "main" → "agent:main:main") before the legacy detector sees them. This caused the early return path to skip logging, breaking doctor-state-migrations tests that assert log.info was called. Extract logMigrationResults helper and call it at every return point. * fix: handle shared stores and ~ expansion in migration P1: When session.store has no {agentId}, all agents resolve to the same file. Track all agentIds per store path (Map<path, Set<id>>) and run canonicalization once per agent. Skip cross-agent "agent:main:*" remapping when "main" is a legitimate configured agent sharing the store, to avoid merging its data into another agent's namespace. P2: Use expandHomePrefix (environment-aware ~ resolution) instead of os.homedir() in resolveStorePathFromTemplate, matching the runtime resolveStorePath behavior for OPENCLAW_HOME/HOME overrides. * fix: narrow cross-agent remap to provable orphan aliases only Only remap agent:main:* keys where the suffix is a main session alias ("main" or the configured mainKey). Other agent:main:* keys — hooks, subagents, cron sessions, per-sender keys — may be intentional cross-agent references and must not be silently moved into another agent's namespace. * fix: run orphan-key session migration at gateway startup (#29683) * fix: canonicalize cross-agent legacy main aliases in session keys (#29683) * fix: guard shared-store migration against cross-agent legacy alias remap (#29683) * refactor: split session-key migration out of pr 30654 --------- Co-authored-by: Your Name <your_email@example.com> Co-authored-by: Ayaan Zaidi <hi@obviy.us>
113 lines
3.6 KiB
TypeScript
113 lines
3.6 KiB
TypeScript
// Shared config/runtime boundary for plugins that need config loading,
|
|
// config writes, or session-store helpers without importing src internals.
|
|
|
|
export { resolveDefaultAgentId } from "../agents/agent-scope.js";
|
|
export {
|
|
getRuntimeConfigSnapshot,
|
|
loadConfig,
|
|
readConfigFileSnapshotForWrite,
|
|
writeConfigFile,
|
|
} from "../config/io.js";
|
|
export { logConfigUpdated } from "../config/logging.js";
|
|
export { updateConfig } from "../commands/models/shared.js";
|
|
export { resolveChannelModelOverride } from "../channels/model-overrides.js";
|
|
export { resolveMarkdownTableMode } from "../config/markdown-tables.js";
|
|
export {
|
|
resolveChannelGroupPolicy,
|
|
resolveChannelGroupRequireMention,
|
|
type ChannelGroupPolicy,
|
|
} from "../config/group-policy.js";
|
|
export {
|
|
GROUP_POLICY_BLOCKED_LABEL,
|
|
resolveAllowlistProviderRuntimeGroupPolicy,
|
|
resolveDefaultGroupPolicy,
|
|
resolveOpenProviderRuntimeGroupPolicy,
|
|
warnMissingProviderGroupPolicyFallbackOnce,
|
|
} from "../config/runtime-group-policy.js";
|
|
export {
|
|
isNativeCommandsExplicitlyDisabled,
|
|
resolveNativeCommandsEnabled,
|
|
resolveNativeSkillsEnabled,
|
|
} from "../config/commands.js";
|
|
export {
|
|
TELEGRAM_COMMAND_NAME_PATTERN,
|
|
normalizeTelegramCommandName,
|
|
resolveTelegramCustomCommands,
|
|
} from "../config/telegram-custom-commands.js";
|
|
export {
|
|
mapStreamingModeToSlackLegacyDraftStreamMode,
|
|
resolveDiscordPreviewStreamMode,
|
|
resolveSlackNativeStreaming,
|
|
resolveSlackStreamingMode,
|
|
resolveTelegramPreviewStreamMode,
|
|
type SlackLegacyDraftStreamMode,
|
|
type StreamingMode,
|
|
} from "../config/discord-preview-streaming.js";
|
|
export { resolveActiveTalkProviderConfig } from "../config/talk.js";
|
|
export { resolveAgentMaxConcurrent } from "../config/agent-limits.js";
|
|
export { loadCronStore, resolveCronStorePath, saveCronStore } from "../cron/store.js";
|
|
export { applyModelOverrideToSessionEntry } from "../sessions/model-overrides.js";
|
|
export { coerceSecretRef } from "../config/types.secrets.js";
|
|
export {
|
|
resolveConfiguredSecretInputString,
|
|
resolveConfiguredSecretInputWithFallback,
|
|
resolveRequiredConfiguredSecretRefInputString,
|
|
} from "../gateway/resolve-configured-secret-input-string.js";
|
|
export type {
|
|
DiscordAccountConfig,
|
|
DiscordActionConfig,
|
|
DiscordAutoPresenceConfig,
|
|
DiscordExecApprovalConfig,
|
|
DiscordGuildChannelConfig,
|
|
DiscordGuildEntry,
|
|
DiscordIntentsConfig,
|
|
DiscordSlashCommandConfig,
|
|
DmPolicy,
|
|
GroupPolicy,
|
|
MarkdownTableMode,
|
|
OpenClawConfig,
|
|
ReplyToMode,
|
|
SignalReactionNotificationMode,
|
|
SlackAccountConfig,
|
|
SlackChannelConfig,
|
|
SlackReactionNotificationMode,
|
|
SlackSlashCommandConfig,
|
|
TelegramAccountConfig,
|
|
TelegramActionConfig,
|
|
TelegramDirectConfig,
|
|
TelegramExecApprovalConfig,
|
|
TelegramGroupConfig,
|
|
TelegramInlineButtonsScope,
|
|
TelegramNetworkConfig,
|
|
TelegramTopicConfig,
|
|
TtsAutoMode,
|
|
TtsConfig,
|
|
TtsMode,
|
|
TtsModelOverrideConfig,
|
|
TtsProvider,
|
|
} from "../config/types.js";
|
|
export {
|
|
loadSessionStore,
|
|
readSessionUpdatedAt,
|
|
recordSessionMetaFromInbound,
|
|
resolveSessionKey,
|
|
resolveStorePath,
|
|
updateLastRoute,
|
|
updateSessionStore,
|
|
type SessionResetMode,
|
|
type SessionScope,
|
|
} from "../config/sessions.js";
|
|
export { resolveGroupSessionKey } from "../config/sessions/group.js";
|
|
export { canonicalizeMainSessionAlias } from "../config/sessions/main-session.js";
|
|
export {
|
|
evaluateSessionFreshness,
|
|
resolveChannelResetConfig,
|
|
resolveSessionResetPolicy,
|
|
resolveSessionResetType,
|
|
resolveThreadFlag,
|
|
} from "../config/sessions/reset.js";
|
|
export { resolveSessionStoreEntry } from "../config/sessions/store.js";
|
|
export {
|
|
isDangerousNameMatchingEnabled,
|
|
resolveDangerousNameMatchingEnabled,
|
|
} from "../config/dangerous-name-matching.js";
|