merge: resolve v1.21.1 conflicts with custom
Resolve all 10 upstream v1.21.1 merge conflicts into custom, keeping custom's GitLab/Gitea forge customizations layered on upstream while lifting upstream improvements. Restored tr.ts i18n key parity with the custom en.ts dictionary (471 custom forge keys added, en fallback) so the upstream-introduced locale stays in parity. Also stage bun.lock version alignment (1.21.0 -> 1.21.1) that matches the staged package.json bump. Verification: ui + web type-check pass; ui/web tests pass except pre-existing failures on the custom baseline (forge.test.ts, session-actions, issue-1637-2270, routes.test.js fs-stat directory scope).
This commit is contained in:
@@ -214,7 +214,7 @@ Managed health failures are classified as `timeout`, `connection_refused`, `conn
|
||||
- `createSettingsHelpers(dependencies)`: creates settings helper runtime for settings request/response shaping.
|
||||
- Returned API:
|
||||
- `normalizePwaAppName(value, fallback?)`
|
||||
- `sanitizeSettingsUpdate(payload)`
|
||||
- `sanitizeSettingsUpdate(payload)` — whitelist of persisted keys; includes `gitProviders` (validated via `packages/web/server/lib/git-providers/config.js` `sanitizeGitProviders`), which therefore round-trips through GET/PUT `/api/config/settings`.
|
||||
- `mergePersistedSettings(current, changes)`
|
||||
- `formatSettingsResponse(settings)`
|
||||
|
||||
|
||||
@@ -4,7 +4,10 @@ import { registerSmallModelRoutes } from '../small-model/routes.js';
|
||||
import { registerWalkthroughRoutes } from '../walkthrough/routes.js';
|
||||
import { registerSessionGoalRoutes } from '../session-goal/routes.js';
|
||||
import { registerGitHubRoutes } from '../github/routes.js';
|
||||
import { registerGitLabRoutes } from '../gitlab/routes.js';
|
||||
import { registerGiteaRoutes } from '../gitea/routes.js';
|
||||
import { registerGitRoutes } from '../git/routes.js';
|
||||
import { registerGitProviderRoutes } from '../git-providers/routes.js';
|
||||
import { registerDevServerRoutes } from '../dev-servers/routes.js';
|
||||
import { registerMagicPromptRoutes } from '../magic-prompts/routes.js';
|
||||
import { registerSessionFoldersRoutes } from '../session-folders/routes.js';
|
||||
@@ -300,6 +303,9 @@ export const createFeatureRoutesRuntime = (dependencies) => {
|
||||
registerWalkthroughRoutes(app, { getWalkthroughService });
|
||||
registerSessionGoalRoutes(app);
|
||||
registerGitHubRoutes(app);
|
||||
registerGitLabRoutes(app);
|
||||
registerGiteaRoutes(app);
|
||||
registerGitProviderRoutes(app);
|
||||
registerGitRoutes(app);
|
||||
registerDevServerRoutes(app, { scanner: devServerScanner, getOwnPorts });
|
||||
registerMagicPromptRoutes(app, {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { sanitizeGitProviders } from '../git-providers/config.js';
|
||||
import { isAgentMemoryFeatureAvailable } from '../agent-memory/feature-flag.js';
|
||||
|
||||
export const createSettingsHelpers = (dependencies) => {
|
||||
@@ -498,6 +499,10 @@ export const createSettingsHelpers = (dependencies) => {
|
||||
const trimmed = candidate.gitModelId.trim();
|
||||
result.gitModelId = trimmed.length > 0 ? trimmed : undefined;
|
||||
}
|
||||
const gitProviders = sanitizeGitProviders(candidate.gitProviders);
|
||||
if (gitProviders) {
|
||||
result.gitProviders = gitProviders;
|
||||
}
|
||||
if (typeof candidate.pwaAppName === 'string') {
|
||||
result.pwaAppName = normalizePwaAppName(candidate.pwaAppName, undefined);
|
||||
}
|
||||
|
||||
@@ -497,6 +497,46 @@ describe('settings helpers', () => {
|
||||
expect(sanitized.favoriteModels).toEqual(payload.favoriteModels);
|
||||
expect(sanitized.recentModels).toEqual(payload.recentModels);
|
||||
});
|
||||
|
||||
it('round-trips a valid gitProviders payload through sanitizeSettingsUpdate', () => {
|
||||
const helpers = createTestHelpersWithRealSanitizers();
|
||||
const payload = {
|
||||
gitProviders: {
|
||||
github: { apiBaseUrl: 'https://github.example.com/api/v3', detectUrls: ['github.example.com'] },
|
||||
gitlab: { apiBaseUrl: 'gitlab.example.com', detectUrls: [] },
|
||||
gitea: { apiBaseUrl: '', detectUrls: ['gitea.example.com'] },
|
||||
},
|
||||
};
|
||||
|
||||
expect(helpers.sanitizeSettingsUpdate(payload)).toEqual({
|
||||
gitProviders: {
|
||||
github: { apiBaseUrl: 'https://github.example.com/api/v3', detectUrls: ['github.example.com'] },
|
||||
gitlab: { apiBaseUrl: 'https://gitlab.example.com' },
|
||||
gitea: { detectUrls: ['gitea.example.com'] },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('drops malformed gitProviders payloads entirely', () => {
|
||||
const helpers = createTestHelpersWithRealSanitizers();
|
||||
|
||||
expect(helpers.sanitizeSettingsUpdate({ gitProviders: 'not-an-object' })).toEqual({});
|
||||
expect(helpers.sanitizeSettingsUpdate({ gitProviders: [] })).toEqual({});
|
||||
expect(helpers.sanitizeSettingsUpdate({ gitProviders: null })).toEqual({});
|
||||
expect(helpers.sanitizeSettingsUpdate({ gitProviders: { unknown: { apiBaseUrl: 'https://x.example.com' } } })).toEqual({});
|
||||
expect(helpers.sanitizeSettingsUpdate({ gitProviders: { github: { apiBaseUrl: ' ' } } })).toEqual({});
|
||||
expect(helpers.sanitizeSettingsUpdate({ gitProviders: { github: { detectUrls: 'github.example.com' } } })).toEqual({});
|
||||
});
|
||||
|
||||
it('normalizes gitProviders apiBaseUrl scheme and strips trailing slashes', () => {
|
||||
const helpers = createTestHelpersWithRealSanitizers();
|
||||
|
||||
expect(helpers.sanitizeSettingsUpdate({
|
||||
gitProviders: { github: { apiBaseUrl: 'github.example.com/api/v3/' } },
|
||||
})).toEqual({
|
||||
gitProviders: { github: { apiBaseUrl: 'https://github.example.com/api/v3' } },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('session retention settings persistence', () => {
|
||||
|
||||
Reference in New Issue
Block a user