mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-04-18 11:31:30 +00:00
refactor(providers): move session message delegation into sessions service
Move provider-backed session history and message normalization calls out of the generic providers service so the service name reflects the behavior it owns. Add a dedicated sessions service for listing session-capable providers, normalizing live provider events, and fetching persisted session history through the provider registry. Update realtime handlers and the unified messages route to depend on `sessionsService` instead of `providersService`. This separates session message operations from other provider concerns such as auth and MCP, keeping the provider services easier to navigate as the module grows.
This commit is contained in:
@@ -24,7 +24,7 @@ import {
|
||||
notifyRunStopped,
|
||||
notifyUserIfEnabled
|
||||
} from './services/notification-orchestrator.js';
|
||||
import { providersService } from './modules/providers/services/providers.service.js';
|
||||
import { sessionsService } from './modules/providers/services/sessions.service.js';
|
||||
import { createNormalizedMessage } from './shared/utils.js';
|
||||
|
||||
const activeSessions = new Map();
|
||||
@@ -649,7 +649,7 @@ async function queryClaudeSDK(command, options = {}, ws) {
|
||||
const sid = capturedSessionId || sessionId || null;
|
||||
|
||||
// Use adapter to normalize SDK events into NormalizedMessage[]
|
||||
const normalized = providersService.normalizeMessage('claude', transformedMessage, sid);
|
||||
const normalized = sessionsService.normalizeMessage('claude', transformedMessage, sid);
|
||||
for (const msg of normalized) {
|
||||
// Preserve parentToolUseId from SDK wrapper for subagent tool grouping
|
||||
if (transformedMessage.parentToolUseId && !msg.parentToolUseId) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { spawn } from 'child_process';
|
||||
import crossSpawn from 'cross-spawn';
|
||||
import { notifyRunFailed, notifyRunStopped } from './services/notification-orchestrator.js';
|
||||
import { providersService } from './modules/providers/services/providers.service.js';
|
||||
import { sessionsService } from './modules/providers/services/sessions.service.js';
|
||||
import { createNormalizedMessage } from './shared/utils.js';
|
||||
|
||||
// Use cross-spawn on Windows for better command execution
|
||||
@@ -189,7 +189,7 @@ async function spawnCursor(command, options = {}, ws) {
|
||||
case 'assistant':
|
||||
// Accumulate assistant message chunks
|
||||
if (response.message && response.message.content && response.message.content.length > 0) {
|
||||
const normalized = providersService.normalizeMessage('cursor', response, capturedSessionId || sessionId || null);
|
||||
const normalized = sessionsService.normalizeMessage('cursor', response, capturedSessionId || sessionId || null);
|
||||
for (const msg of normalized) ws.send(msg);
|
||||
}
|
||||
break;
|
||||
@@ -219,7 +219,7 @@ async function spawnCursor(command, options = {}, ws) {
|
||||
}
|
||||
|
||||
// If not JSON, send as stream delta via adapter
|
||||
const normalized = providersService.normalizeMessage('cursor', line, capturedSessionId || sessionId || null);
|
||||
const normalized = sessionsService.normalizeMessage('cursor', line, capturedSessionId || sessionId || null);
|
||||
for (const msg of normalized) ws.send(msg);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Gemini Response Handler - JSON Stream processing
|
||||
import { providersService } from './modules/providers/services/providers.service.js';
|
||||
import { sessionsService } from './modules/providers/services/sessions.service.js';
|
||||
|
||||
class GeminiResponseHandler {
|
||||
constructor(ws, options = {}) {
|
||||
@@ -56,7 +56,7 @@ class GeminiResponseHandler {
|
||||
}
|
||||
|
||||
// Normalize via adapter and send all resulting messages
|
||||
const normalized = providersService.normalizeMessage('gemini', event, sid);
|
||||
const normalized = sessionsService.normalizeMessage('gemini', event, sid);
|
||||
for (const msg of normalized) {
|
||||
this.ws.send(msg);
|
||||
}
|
||||
|
||||
@@ -7,17 +7,23 @@ import type {
|
||||
} from '@/shared/types.js';
|
||||
|
||||
/**
|
||||
* Application service for provider message operations.
|
||||
* Application service for provider-backed session message operations.
|
||||
*
|
||||
* Callers pass a provider id and this service resolves the concrete provider
|
||||
* class, keeping normalization/history call sites decoupled from implementation
|
||||
* file layout.
|
||||
*/
|
||||
export const providersService = {
|
||||
export const sessionsService = {
|
||||
/**
|
||||
* Lists provider ids that can load session history and normalize live messages.
|
||||
*/
|
||||
listProviderIds(): LLMProvider[] {
|
||||
return providerRegistry.listProviders().map((provider) => provider.id);
|
||||
},
|
||||
|
||||
/**
|
||||
* Normalizes one provider-native event into frontend session message events.
|
||||
*/
|
||||
normalizeMessage(
|
||||
providerName: string,
|
||||
raw: unknown,
|
||||
@@ -26,6 +32,9 @@ export const providersService = {
|
||||
return providerRegistry.resolveProvider(providerName).normalizeMessage(raw, sessionId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetches normalized persisted session history for one provider/session pair.
|
||||
*/
|
||||
fetchHistory(
|
||||
providerName: string,
|
||||
sessionId: string,
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
import { Codex } from '@openai/codex-sdk';
|
||||
import { notifyRunFailed, notifyRunStopped } from './services/notification-orchestrator.js';
|
||||
import { providersService } from './modules/providers/services/providers.service.js';
|
||||
import { sessionsService } from './modules/providers/services/sessions.service.js';
|
||||
import { createNormalizedMessage } from './shared/utils.js';
|
||||
|
||||
// Track active sessions
|
||||
@@ -264,7 +264,7 @@ export async function queryCodex(command, options = {}, ws) {
|
||||
const transformed = transformCodexEvent(event);
|
||||
|
||||
// Normalize the transformed event into NormalizedMessage(s) via adapter
|
||||
const normalizedMsgs = providersService.normalizeMessage('codex', transformed, currentSessionId);
|
||||
const normalizedMsgs = sessionsService.normalizeMessage('codex', transformed, currentSessionId);
|
||||
for (const msg of normalizedMsgs) {
|
||||
sendMessage(ws, msg);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
import express from 'express';
|
||||
import { providersService } from '../modules/providers/services/providers.service.js';
|
||||
import { sessionsService } from '../modules/providers/services/sessions.service.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
@@ -38,13 +38,13 @@ router.get('/:sessionId/messages', async (req, res) => {
|
||||
: null;
|
||||
const offset = parseInt(req.query.offset || '0', 10);
|
||||
|
||||
const availableProviders = providersService.listProviderIds();
|
||||
const availableProviders = sessionsService.listProviderIds();
|
||||
if (!availableProviders.includes(provider)) {
|
||||
const available = availableProviders.join(', ');
|
||||
return res.status(400).json({ error: `Unknown provider: ${provider}. Available: ${available}` });
|
||||
}
|
||||
|
||||
const result = await providersService.fetchHistory(provider, sessionId, {
|
||||
const result = await sessionsService.fetchHistory(provider, sessionId, {
|
||||
projectName,
|
||||
projectPath,
|
||||
limit,
|
||||
|
||||
Reference in New Issue
Block a user