feat: refine codex live chat context flows
This commit is contained in:
@@ -1,6 +1,14 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { mergeDefaultChatTypes, resolveAppConfigByOrigin } from './app-config-service.js';
|
||||
import {
|
||||
mergeDefaultChatTypes,
|
||||
migrateLegacyChatTypeContexts,
|
||||
stripBuiltInChatTypes,
|
||||
resolveAppConfigByOrigin,
|
||||
resolveCanonicalChatTypesFromConfig,
|
||||
resolveCanonicalChatContextSettingsFromConfig,
|
||||
stripChatContextSettingsFromScopedAppConfigs,
|
||||
} from './app-config-service.js';
|
||||
|
||||
test('mergeDefaultChatTypes preserves saved edits for built-in chat types', () => {
|
||||
const merged = mergeDefaultChatTypes([
|
||||
@@ -64,9 +72,74 @@ test('mergeDefaultChatTypes still appends missing built-in chat types', () => {
|
||||
assert.ok(merged.some((item) => item.id === 'layout-editor-execution'));
|
||||
assert.ok(merged.some((item) => item.id === 'api-request-template'));
|
||||
assert.ok(merged.some((item) => item.id === 'general-inquiry'));
|
||||
assert.ok(!merged.some((item) => item.id === 'plan-checklist-execution'));
|
||||
assert.ok(!merged.some((item) => item.id === 'layout-editor-guided-execution'));
|
||||
});
|
||||
|
||||
test('stripBuiltInChatTypes removes built-in chat type ids from saved list', () => {
|
||||
const stripped = stripBuiltInChatTypes([
|
||||
{
|
||||
id: 'general-request',
|
||||
name: '일반 요청',
|
||||
description: 'builtin',
|
||||
permissions: ['token-user'],
|
||||
enabled: true,
|
||||
updatedAt: '2026-05-08T00:00:00.000Z',
|
||||
},
|
||||
{
|
||||
id: 'plan-checklist-execution',
|
||||
name: 'Plan 체크리스트 실행',
|
||||
description: 'custom-seeded',
|
||||
permissions: ['token-user'],
|
||||
enabled: true,
|
||||
updatedAt: '2026-05-08T00:00:00.000Z',
|
||||
},
|
||||
{
|
||||
id: 'custom-support-flow',
|
||||
name: '운영 문의 전용',
|
||||
description: 'custom',
|
||||
permissions: ['token-user'],
|
||||
enabled: true,
|
||||
updatedAt: '2026-05-08T00:00:00.000Z',
|
||||
},
|
||||
]);
|
||||
|
||||
assert.deepEqual(stripped.map((item) => item.id), ['custom-support-flow', 'plan-checklist-execution']);
|
||||
});
|
||||
|
||||
test('migrateLegacyChatTypeContexts moves legacy plan checklist chat type into default context settings', () => {
|
||||
const migrated = migrateLegacyChatTypeContexts(
|
||||
{
|
||||
defaultContexts: [],
|
||||
chatTypeDefaults: [
|
||||
{
|
||||
chatTypeId: 'plan-checklist-execution',
|
||||
defaultContextIds: ['legacy-linked-context'],
|
||||
updatedAt: '2026-05-08T00:00:00.000Z',
|
||||
},
|
||||
],
|
||||
roomContexts: [],
|
||||
},
|
||||
[
|
||||
{
|
||||
id: 'plan-checklist-execution',
|
||||
name: 'Plan 체크리스트 실행',
|
||||
description: 'legacy plan context',
|
||||
permissions: ['token-user'],
|
||||
enabled: true,
|
||||
updatedAt: '2026-05-08T00:00:00.000Z',
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
assert.equal(migrated.defaultContexts.some((item) => item.id === 'chat-default-plan-checklist-execution'), true);
|
||||
assert.equal(
|
||||
migrated.defaultContexts.find((item) => item.id === 'chat-default-plan-checklist-execution')?.content,
|
||||
'legacy plan context',
|
||||
);
|
||||
assert.equal(migrated.chatTypeDefaults.some((item) => item.chatTypeId === 'plan-checklist-execution'), false);
|
||||
});
|
||||
|
||||
test('resolveAppConfigByOrigin prefers scoped app config over legacy global config', () => {
|
||||
const resolved = resolveAppConfigByOrigin(
|
||||
{
|
||||
@@ -112,3 +185,149 @@ test('resolveAppConfigByOrigin falls back to legacy global config when scoped co
|
||||
|
||||
assert.equal(resolved.chat?.receiveRoomNotifications, true);
|
||||
});
|
||||
|
||||
test('resolveCanonicalChatContextSettingsFromConfig prefers global chat context settings over stale scoped entries', () => {
|
||||
const resolved = resolveCanonicalChatContextSettingsFromConfig(
|
||||
{
|
||||
chatContextSettings: {
|
||||
defaultContexts: [
|
||||
{
|
||||
id: 'global-a',
|
||||
title: '전역 A',
|
||||
content: 'global',
|
||||
enabled: true,
|
||||
updatedAt: '2026-05-08T00:00:00.000Z',
|
||||
},
|
||||
{
|
||||
id: 'global-b',
|
||||
title: '전역 B',
|
||||
content: 'global',
|
||||
enabled: true,
|
||||
updatedAt: '2026-05-08T00:00:00.000Z',
|
||||
},
|
||||
],
|
||||
},
|
||||
scopedAppConfigs: {
|
||||
'https://test.sm-home.cloud': {
|
||||
config: {
|
||||
chatContextSettings: {
|
||||
defaultContexts: [
|
||||
{
|
||||
id: 'scoped-a',
|
||||
title: '스코프 A',
|
||||
content: 'scoped',
|
||||
enabled: true,
|
||||
updatedAt: '2026-05-01T00:00:00.000Z',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'https://test.sm-home.cloud',
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
resolved.defaultContexts.map((item) => item.id),
|
||||
['global-a', 'global-b'],
|
||||
);
|
||||
});
|
||||
|
||||
test('resolveCanonicalChatContextSettingsFromConfig falls back to scoped settings only when global settings are empty', () => {
|
||||
const resolved = resolveCanonicalChatContextSettingsFromConfig(
|
||||
{
|
||||
scopedAppConfigs: {
|
||||
'https://test.sm-home.cloud': {
|
||||
config: {
|
||||
chatContextSettings: {
|
||||
defaultContexts: [
|
||||
{
|
||||
id: 'scoped-a',
|
||||
title: '스코프 A',
|
||||
content: 'scoped',
|
||||
enabled: true,
|
||||
updatedAt: '2026-05-01T00:00:00.000Z',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'https://test.sm-home.cloud',
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
resolved.defaultContexts.map((item) => item.id),
|
||||
['scoped-a'],
|
||||
);
|
||||
});
|
||||
|
||||
test('resolveCanonicalChatTypesFromConfig merges global chat types with stale scoped entries', () => {
|
||||
const resolved = resolveCanonicalChatTypesFromConfig(
|
||||
{
|
||||
chatTypes: [
|
||||
{
|
||||
id: 'verification-test-generation',
|
||||
name: '검증 밑 테스트 생성',
|
||||
description: 'global',
|
||||
permissions: ['token-user'],
|
||||
enabled: true,
|
||||
updatedAt: '2026-05-08T08:15:18.440Z',
|
||||
},
|
||||
],
|
||||
scopedAppConfigs: {
|
||||
'https://test.sm-home.cloud': {
|
||||
config: {
|
||||
chatTypes: [
|
||||
{
|
||||
id: 'general-request',
|
||||
name: '일반 요청',
|
||||
description: 'scoped',
|
||||
permissions: ['token-user'],
|
||||
enabled: true,
|
||||
updatedAt: '2026-05-01T00:00:00.000Z',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'https://test.sm-home.cloud',
|
||||
);
|
||||
|
||||
assert.ok(resolved);
|
||||
assert.equal(resolved.some((item) => item.id === 'verification-test-generation'), true);
|
||||
assert.equal(resolved.some((item) => item.id === 'general-request'), true);
|
||||
});
|
||||
|
||||
test('stripChatContextSettingsFromScopedAppConfigs removes stale scoped chat context settings only', () => {
|
||||
const stripped = stripChatContextSettingsFromScopedAppConfigs({
|
||||
scopedAppConfigs: {
|
||||
'https://test.sm-home.cloud': {
|
||||
config: {
|
||||
chatContextSettings: {
|
||||
defaultContexts: [{ id: 'legacy', title: 'legacy', content: 'legacy', enabled: true }],
|
||||
},
|
||||
chat: {
|
||||
receiveRoomNotifications: false,
|
||||
},
|
||||
},
|
||||
updatedAt: '2026-05-08T00:00:00.000Z',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(stripped.changed, true);
|
||||
assert.deepEqual(stripped.scopedConfigs, {
|
||||
'https://test.sm-home.cloud': {
|
||||
config: {
|
||||
chat: {
|
||||
receiveRoomNotifications: false,
|
||||
},
|
||||
},
|
||||
updatedAt: '2026-05-08T00:00:00.000Z',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user