merge: resolve v1.23.0 upstream conflicts, preserve custom git provider config
Resolved conflicts in 8 files by taking upstream refactored code: - desktop.ts: re-export DesktopSettings from registry - openchamberConfig.ts: simplified project setup client - persistence.ts: registry-derived settings, add git provider hydration - search.ts: upstream search entries + git provider entries - useConfigStore.ts: loadDesktopSettings() path - settings-helpers.js: add gitProviderId/gitModelId/gitProviders sanitization - DOCUMENTATION.md: upstream walkthrough docs - vite.config.ts: upstream SW glob patterns Custom fork additions preserved: - gitProviderId, gitModelId, gitProviders fields in settings registry - Git provider domain store hydration in persistence.ts - Git provider search entries in search.ts - Git provider sanitization in settings-helpers.js
This commit is contained in:
@@ -97,6 +97,7 @@ import { createSessionSteerRuntime, registerSessionSteerRoutes } from './lib/ses
|
||||
import { createPlanGateRuntime, registerPlanGateRoutes } from './lib/plan-gate/runtime.js';
|
||||
import { createGracefulShutdownRuntime } from './lib/opencode/shutdown-runtime.js';
|
||||
import { createProjectConfigRuntime } from './lib/projects/project-config.js';
|
||||
import { migrateLegacyUserDirs } from './lib/data-dir-migration.js';
|
||||
import { createProjectContextRuntime } from './lib/project-context/runtime.js';
|
||||
import { createAgentMemoryRuntime } from './lib/agent-memory/runtime.js';
|
||||
import { createAgentMemoryActions } from './lib/agent-memory/actions.js';
|
||||
@@ -120,6 +121,10 @@ import { createScheduledTaskService } from './lib/scheduled-tasks/service.js';
|
||||
import { createOpenChamberControlService } from './lib/openchamber-control/service.js';
|
||||
import { OpenChamberControlError } from './lib/openchamber-control/error.js';
|
||||
import webPush from 'web-push';
|
||||
import { applyConnectAttemptTimeout } from './lib/network-defaults.js';
|
||||
|
||||
// Background CLI launches enter here in a fresh process, without CLI defaults.
|
||||
applyConnectAttemptTimeout();
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
@@ -263,14 +268,20 @@ const normalizeManagedRemoteTunnelPresets = (...args) =>
|
||||
const normalizeManagedRemoteTunnelPresetTokens = (...args) =>
|
||||
settingsNormalizationRuntime.normalizeManagedRemoteTunnelPresetTokens(...args);
|
||||
const isUnsafeSkillRelativePath = (...args) => settingsNormalizationRuntime.isUnsafeSkillRelativePath(...args);
|
||||
const sanitizeTypographySizesPartial = (...args) =>
|
||||
settingsNormalizationRuntime.sanitizeTypographySizesPartial(...args);
|
||||
const normalizeStringArray = (...args) => settingsNormalizationRuntime.normalizeStringArray(...args);
|
||||
const sanitizeModelRefs = (...args) => settingsNormalizationRuntime.sanitizeModelRefs(...args);
|
||||
const sanitizeSkillCatalogs = (...args) => settingsNormalizationRuntime.sanitizeSkillCatalogs(...args);
|
||||
const sanitizeProjects = (...args) => settingsNormalizationRuntime.sanitizeProjects(...args);
|
||||
|
||||
const OPENCHAMBER_USER_CONFIG_ROOT = path.join(os.homedir(), '.config', 'openchamber');
|
||||
// Every OpenChamber-owned file and folder hangs off one root: the default
|
||||
// `~/.config/openchamber`, or `OPENCHAMBER_DATA_DIR` when set. The user
|
||||
// folders (`projects/`, `themes/`, `speech-models/`) are copied into a custom
|
||||
// root once at startup (`migrateLegacyUserDirs`), because they used to ignore
|
||||
// the variable.
|
||||
const OPENCHAMBER_DEFAULT_CONFIG_ROOT = path.join(os.homedir(), '.config', 'openchamber');
|
||||
const OPENCHAMBER_USER_CONFIG_ROOT = process.env.OPENCHAMBER_DATA_DIR
|
||||
? path.resolve(process.env.OPENCHAMBER_DATA_DIR)
|
||||
: OPENCHAMBER_DEFAULT_CONFIG_ROOT;
|
||||
const OPENCHAMBER_USER_THEMES_DIR = path.join(OPENCHAMBER_USER_CONFIG_ROOT, 'themes');
|
||||
const OPENCHAMBER_PROJECTS_CONFIG_DIR = path.join(OPENCHAMBER_USER_CONFIG_ROOT, 'projects');
|
||||
// OPENCHAMBER_CHATS_DIR relocates managed chat worktrees — needed when the
|
||||
@@ -309,9 +320,7 @@ const maybeCacheSessionInfoFromEvent = (...args) => notificationTemplateRuntime.
|
||||
const buildTemplateVariables = (...args) => notificationTemplateRuntime.buildTemplateVariables(...args);
|
||||
const getCachedZenModels = (...args) => notificationTemplateRuntime.getCachedZenModels(...args);
|
||||
|
||||
const OPENCHAMBER_DATA_DIR = process.env.OPENCHAMBER_DATA_DIR
|
||||
? path.resolve(process.env.OPENCHAMBER_DATA_DIR)
|
||||
: path.join(os.homedir(), '.config', 'openchamber');
|
||||
const OPENCHAMBER_DATA_DIR = OPENCHAMBER_USER_CONFIG_ROOT;
|
||||
const SETTINGS_FILE_PATH = path.join(OPENCHAMBER_DATA_DIR, 'settings.json');
|
||||
const PUSH_SUBSCRIPTIONS_FILE_PATH = path.join(OPENCHAMBER_DATA_DIR, 'push-subscriptions.json');
|
||||
const APNS_TOKENS_FILE_PATH = path.join(OPENCHAMBER_DATA_DIR, 'apns-tokens.json');
|
||||
@@ -349,7 +358,6 @@ const settingsHelpers = createSettingsHelpers({
|
||||
normalizeManagedRemoteTunnelHostname,
|
||||
normalizeManagedRemoteTunnelPresets,
|
||||
normalizeManagedRemoteTunnelPresetTokens,
|
||||
sanitizeTypographySizesPartial,
|
||||
normalizeStringArray,
|
||||
sanitizeModelRefs,
|
||||
sanitizeSkillCatalogs,
|
||||
@@ -488,6 +496,17 @@ const getUpstreamStallTimeoutMs = () => (
|
||||
: DEFAULT_UPSTREAM_STALL_TIMEOUT_MS
|
||||
);
|
||||
|
||||
const movedUserDirs = await migrateLegacyUserDirs({
|
||||
fsPromises,
|
||||
path,
|
||||
dataDir: OPENCHAMBER_USER_CONFIG_ROOT,
|
||||
legacyRoot: OPENCHAMBER_DEFAULT_CONFIG_ROOT,
|
||||
warn: (message) => console.warn(`[data-dir] ${message}`),
|
||||
});
|
||||
if (movedUserDirs.length > 0) {
|
||||
console.log(`[data-dir] Copied ${movedUserDirs.join(', ')} into ${OPENCHAMBER_USER_CONFIG_ROOT}`);
|
||||
}
|
||||
|
||||
const projectConfigRuntime = createProjectConfigRuntime({
|
||||
fsPromises,
|
||||
path,
|
||||
@@ -498,6 +517,7 @@ const projectContextRuntime = createProjectContextRuntime({
|
||||
fsPromises,
|
||||
path,
|
||||
projectsDirPath: OPENCHAMBER_PROJECTS_CONFIG_DIR,
|
||||
resolveSharedPlansDir: (projectId) => projectConfigRuntime.resolveSharedPlansDir(projectId),
|
||||
});
|
||||
|
||||
const agentMemoryRuntime = createAgentMemoryRuntime({
|
||||
@@ -897,7 +917,13 @@ const messageQueueRuntime = createMessageQueueRuntime({
|
||||
buildOpenCodeUrl,
|
||||
getOpenCodeAuthHeaders,
|
||||
sessionKnowledgeRuntime,
|
||||
broadcastGlobalUiEvent,
|
||||
// OpenCode's /global/event SSE proxy cannot carry OpenChamber-owned events.
|
||||
// Use the shared control stream for SSE clients and the existing WS fan-out.
|
||||
broadcastGlobalUiEvent: createGlobalUiEventBroadcaster({
|
||||
sseClients: uiOpenChamberEventClients,
|
||||
wsClients: uiNotificationWsClients,
|
||||
writeSseEvent,
|
||||
}),
|
||||
onPromptSent: (sessionId) => sessionRuntime.markUserMessageSent(sessionId),
|
||||
dataDir: OPENCHAMBER_DATA_DIR,
|
||||
});
|
||||
@@ -1669,6 +1695,12 @@ async function main(options = {}) {
|
||||
const getDesktopRuntimeConfig = typeof options.getDesktopRuntimeConfig === 'function'
|
||||
? options.getDesktopRuntimeConfig
|
||||
: null;
|
||||
const desktopUpdater = options.desktopUpdater
|
||||
&& typeof options.desktopUpdater.check === 'function'
|
||||
&& typeof options.desktopUpdater.install === 'function'
|
||||
&& typeof options.desktopUpdater.restart === 'function'
|
||||
? options.desktopUpdater
|
||||
: null;
|
||||
|
||||
console.log(`Starting OpenChamber on port ${port === 0 ? 'auto' : port}`);
|
||||
|
||||
@@ -1703,7 +1735,10 @@ async function main(options = {}) {
|
||||
res.setHeader('Access-Control-Allow-Origin', origin);
|
||||
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
||||
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,DELETE,OPTIONS');
|
||||
res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization,Accept,X-Requested-With,Cache-Control,X-OpenCode-Directory,X-OpenCode-Directory-Encoding,Ngrok-Skip-Browser-Warning');
|
||||
// The packaged desktop UI (openchamber-ui://) and the dev UI sit on a
|
||||
// different origin, so every custom request header must be listed here or
|
||||
// the browser refuses the request at preflight, before it reaches a route.
|
||||
res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization,Accept,X-Requested-With,Cache-Control,X-OpenCode-Directory,X-OpenCode-Directory-Encoding,Ngrok-Skip-Browser-Warning,X-OpenChamber-Surface');
|
||||
res.setHeader('Access-Control-Expose-Headers', 'x-next-cursor');
|
||||
res.setHeader('Vary', 'Origin');
|
||||
if (req.method === 'OPTIONS') {
|
||||
@@ -1844,6 +1879,7 @@ async function main(options = {}) {
|
||||
getCachedZenModels,
|
||||
setAutoAcceptSession,
|
||||
agentToolRuntime,
|
||||
desktopUpdater,
|
||||
});
|
||||
uiAuthController = bootstrapResult.uiAuthController;
|
||||
realtimeProxyRuntime = attachRealtimeProxy({
|
||||
|
||||
Reference in New Issue
Block a user