ГЛОБАЛЬНЫЙ РЕФАКТОРИНГ АРХИТЕКТУРЫ - Архитектурный фундамент: capability-guard, navigation state и трассируемый route-контракт
This commit is contained in:
@@ -1,8 +1,18 @@
|
||||
import { nanoid } from "nanoid";
|
||||
import type { AssistantConversationItem, AssistantSessionState } from "../types/assistant";
|
||||
import type { InvestigationState } from "../types/stage1Contracts";
|
||||
import { FEATURE_ASSISTANT_INVESTIGATION_STATE_V1 } from "../config";
|
||||
import type { AddressNavigationState } from "../types/addressNavigation";
|
||||
import {
|
||||
FEATURE_ASSISTANT_ADDRESS_NAVIGATION_STATE_V1,
|
||||
FEATURE_ASSISTANT_INVESTIGATION_STATE_V1
|
||||
} from "../config";
|
||||
import { cloneInvestigationState, createEmptyInvestigationState } from "./investigationState";
|
||||
import {
|
||||
cloneAddressNavigationState,
|
||||
createEmptyAddressNavigationState,
|
||||
evolveAddressNavigationStateWithAssistantItem,
|
||||
normalizeAddressNavigationState
|
||||
} from "./addressNavigationState";
|
||||
|
||||
const MAX_ITEMS_PER_SESSION = 200;
|
||||
|
||||
@@ -18,13 +28,15 @@ function cloneSession(state: AssistantSessionState): AssistantSessionState {
|
||||
session_id: state.session_id,
|
||||
updated_at: state.updated_at,
|
||||
items: state.items.map(cloneItem),
|
||||
investigation_state: cloneInvestigationState(state.investigation_state)
|
||||
investigation_state: cloneInvestigationState(state.investigation_state),
|
||||
address_navigation_state: cloneAddressNavigationState(state.address_navigation_state)
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeSessionShape(state: AssistantSessionState): AssistantSessionState {
|
||||
const legacy = state as AssistantSessionState & {
|
||||
investigation_state?: InvestigationState | null;
|
||||
address_navigation_state?: AddressNavigationState | null;
|
||||
items?: AssistantConversationItem[];
|
||||
updated_at?: string;
|
||||
};
|
||||
@@ -33,10 +45,18 @@ function normalizeSessionShape(state: AssistantSessionState): AssistantSessionSt
|
||||
FEATURE_ASSISTANT_INVESTIGATION_STATE_V1
|
||||
? legacy.investigation_state ?? createEmptyInvestigationState(state.session_id)
|
||||
: legacy.investigation_state ?? null;
|
||||
const addressNavigationState =
|
||||
FEATURE_ASSISTANT_ADDRESS_NAVIGATION_STATE_V1
|
||||
? normalizeAddressNavigationState(
|
||||
legacy.address_navigation_state ?? createEmptyAddressNavigationState(state.session_id),
|
||||
state.session_id
|
||||
)
|
||||
: legacy.address_navigation_state ?? null;
|
||||
|
||||
state.items = normalizedItems;
|
||||
state.updated_at = typeof legacy.updated_at === "string" && legacy.updated_at.trim() ? legacy.updated_at : new Date().toISOString();
|
||||
state.investigation_state = investigationState;
|
||||
state.address_navigation_state = addressNavigationState;
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -53,7 +73,8 @@ export class AssistantSessionStore {
|
||||
session_id: resolvedId,
|
||||
updated_at: new Date().toISOString(),
|
||||
items: [],
|
||||
investigation_state: FEATURE_ASSISTANT_INVESTIGATION_STATE_V1 ? createEmptyInvestigationState(resolvedId) : null
|
||||
investigation_state: FEATURE_ASSISTANT_INVESTIGATION_STATE_V1 ? createEmptyInvestigationState(resolvedId) : null,
|
||||
address_navigation_state: FEATURE_ASSISTANT_ADDRESS_NAVIGATION_STATE_V1 ? createEmptyAddressNavigationState(resolvedId) : null
|
||||
};
|
||||
this.sessions.set(resolvedId, created);
|
||||
return cloneSession(created);
|
||||
@@ -65,6 +86,14 @@ export class AssistantSessionStore {
|
||||
if (session.items.length > MAX_ITEMS_PER_SESSION) {
|
||||
session.items = session.items.slice(session.items.length - MAX_ITEMS_PER_SESSION);
|
||||
}
|
||||
if (FEATURE_ASSISTANT_ADDRESS_NAVIGATION_STATE_V1) {
|
||||
const baseNavigationState = normalizeAddressNavigationState(session.address_navigation_state, sessionId);
|
||||
session.address_navigation_state = evolveAddressNavigationStateWithAssistantItem(
|
||||
baseNavigationState,
|
||||
item,
|
||||
Math.max(0, session.items.length - 1)
|
||||
);
|
||||
}
|
||||
session.updated_at = new Date().toISOString();
|
||||
return cloneItem(item);
|
||||
}
|
||||
@@ -81,6 +110,25 @@ export class AssistantSessionStore {
|
||||
return cloneInvestigationState(session.investigation_state);
|
||||
}
|
||||
|
||||
public getAddressNavigationState(sessionId: string): AddressNavigationState | null {
|
||||
const session = this.ensureMutableSession(sessionId);
|
||||
if (!FEATURE_ASSISTANT_ADDRESS_NAVIGATION_STATE_V1) {
|
||||
return null;
|
||||
}
|
||||
return cloneAddressNavigationState(session.address_navigation_state);
|
||||
}
|
||||
|
||||
public setAddressNavigationState(sessionId: string, state: AddressNavigationState | null): AddressNavigationState | null {
|
||||
const session = this.ensureMutableSession(sessionId);
|
||||
if (!FEATURE_ASSISTANT_ADDRESS_NAVIGATION_STATE_V1) {
|
||||
session.address_navigation_state = null;
|
||||
return null;
|
||||
}
|
||||
session.address_navigation_state = normalizeAddressNavigationState(state, sessionId);
|
||||
session.updated_at = new Date().toISOString();
|
||||
return cloneAddressNavigationState(session.address_navigation_state);
|
||||
}
|
||||
|
||||
private ensureMutableSession(sessionId: string): AssistantSessionState {
|
||||
const existing = this.sessions.get(sessionId);
|
||||
if (existing) {
|
||||
@@ -90,7 +138,8 @@ export class AssistantSessionStore {
|
||||
session_id: sessionId,
|
||||
updated_at: new Date().toISOString(),
|
||||
items: [],
|
||||
investigation_state: FEATURE_ASSISTANT_INVESTIGATION_STATE_V1 ? createEmptyInvestigationState(sessionId) : null
|
||||
investigation_state: FEATURE_ASSISTANT_INVESTIGATION_STATE_V1 ? createEmptyInvestigationState(sessionId) : null,
|
||||
address_navigation_state: FEATURE_ASSISTANT_ADDRESS_NAVIGATION_STATE_V1 ? createEmptyAddressNavigationState(sessionId) : null
|
||||
};
|
||||
this.sessions.set(sessionId, created);
|
||||
return created;
|
||||
|
||||
Reference in New Issue
Block a user