mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-05-16 01:12:46 +00:00
feat: add comprehensive tests for LLM sessions and skills services
- Introduced tests for session synchronization, file delegation, session updates, and artifact deletion in sessions.test.ts. - Added tests for skill discovery and invocation across various scopes in skills.test.ts. - Created new types for MCP and provider skills to enhance type safety and clarity. - Refactored routes to use the updated llmSessionsService from the i-runtime module. - Removed deprecated session indexers and consolidated related functionality.
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import type { IProvider } from '@/modules/llm/providers/provider.interface.js';
|
||||
import { ClaudeProvider } from '@/modules/llm/providers/claude.provider.js';
|
||||
import { CodexProvider } from '@/modules/llm/providers/codex.provider.js';
|
||||
import { CursorProvider } from '@/modules/llm/providers/cursor.provider.js';
|
||||
import { GeminiProvider } from '@/modules/llm/providers/gemini.provider.js';
|
||||
import type { IProvider } from '@/modules/ai-runtime/types/index.js';
|
||||
import { ClaudeProvider } from '@/modules/ai-runtime/providers/claude/claude.provider.js';
|
||||
import { CodexProvider } from '@/modules/ai-runtime/providers/codex/codex.provider.js';
|
||||
import { CursorProvider } from '@/modules/ai-runtime/providers/cursor/cursor.provider.js';
|
||||
import { GeminiProvider } from '@/modules/ai-runtime/providers/gemini/gemini.provider.js';
|
||||
import type { LLMProvider } from '@/shared/types/app.js';
|
||||
import { AppError } from '@/shared/utils/app-error.js';
|
||||
|
||||
@@ -3,10 +3,10 @@ import express, { type NextFunction, type Request, type Response } from 'express
|
||||
import { asyncHandler } from '@/shared/http/async-handler.js';
|
||||
import { AppError } from '@/shared/utils/app-error.js';
|
||||
import { createApiErrorResponse, createApiSuccessResponse } from '@/shared/http/api-response.js';
|
||||
import { llmService } from '@/modules/llm/services/llm.service.js';
|
||||
import { llmSessionsService } from '@/modules/llm/services/sessions.service.js';
|
||||
import type { McpScope, McpTransport, UpsertProviderMcpServerInput } from '@/modules/llm/providers/provider.interface.js';
|
||||
import { llmMessagesUnifier } from '@/modules/llm/services/messages-unifier.service.js';
|
||||
import { llmService } from '@/modules/ai-runtime/services/ai-runtime.service.js';
|
||||
import { llmSessionsService } from '@/modules/ai-runtime/services/sessions.service.js';
|
||||
import type { McpScope, McpTransport, UpsertProviderMcpServerInput } from '@/modules/ai-runtime/types/index.js';
|
||||
import { llmMessagesUnifier } from '@/modules/ai-runtime/services/messages-unifier.service.js';
|
||||
import type { LLMProvider } from '@/shared/types/app.js';
|
||||
import { logger } from '@/shared/utils/logger.js';
|
||||
|
||||
@@ -530,7 +530,7 @@ router.use((error: unknown, _req: Request, res: Response, _next: NextFunction) =
|
||||
|
||||
const message = error instanceof Error ? error.message : 'Unexpected LLM route failure.';
|
||||
logger.error(message, {
|
||||
module: 'llm.routes',
|
||||
module: 'ai-runtime.routes',
|
||||
});
|
||||
|
||||
res.status(500).json(createApiErrorResponse('INTERNAL_ERROR', message));
|
||||
@@ -9,7 +9,7 @@ import type {
|
||||
ProviderSessionEvent,
|
||||
ProviderSessionSnapshot,
|
||||
StartSessionInput,
|
||||
} from '@/modules/llm/providers/provider.interface.js';
|
||||
} from '@/modules/ai-runtime/types/index.js';
|
||||
import type { LLMProvider } from '@/shared/types/app.js';
|
||||
|
||||
const MAX_EVENT_BUFFER_SIZE = 2_000;
|
||||
@@ -4,14 +4,14 @@ import type { ChildProcessWithoutNullStreams } from 'node:child_process';
|
||||
|
||||
import spawn from 'cross-spawn';
|
||||
|
||||
import { AbstractProvider } from '@/modules/llm/providers/abstract.provider.js';
|
||||
import { AbstractProvider } from '@/modules/ai-runtime/providers/base/abstract.provider.js';
|
||||
import type {
|
||||
MutableProviderSession,
|
||||
ProviderCapabilities,
|
||||
ProviderSessionEvent,
|
||||
ProviderSessionSnapshot,
|
||||
StartSessionInput,
|
||||
} from '@/modules/llm/providers/provider.interface.js';
|
||||
} from '@/modules/ai-runtime/types/index.js';
|
||||
import { createStreamLineAccumulator } from '@/shared/platform/stream.js';
|
||||
import type { LLMProvider } from '@/shared/types/app.js';
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { randomUUID } from 'node:crypto';
|
||||
|
||||
import { AbstractProvider } from '@/modules/llm/providers/abstract.provider.js';
|
||||
import { AbstractProvider } from '@/modules/ai-runtime/providers/base/abstract.provider.js';
|
||||
import type {
|
||||
MutableProviderSession,
|
||||
ProviderCapabilities,
|
||||
ProviderSessionEvent,
|
||||
ProviderSessionSnapshot,
|
||||
StartSessionInput,
|
||||
} from '@/modules/llm/providers/provider.interface.js';
|
||||
} from '@/modules/ai-runtime/types/index.js';
|
||||
import type { LLMProvider } from '@/shared/types/app.js';
|
||||
|
||||
type CreateSdkExecutionInput = StartSessionInput & {
|
||||
@@ -6,8 +6,8 @@ import type {
|
||||
McpScope,
|
||||
ProviderMcpServer,
|
||||
UpsertProviderMcpServerInput,
|
||||
} from '@/modules/llm/providers/provider.interface.js';
|
||||
import { BaseProviderMcpRuntime } from '@/modules/llm/providers/runtimes/base-provider-mcp.runtime.js';
|
||||
} from '@/modules/ai-runtime/types/index.js';
|
||||
import { BaseProviderMcpRuntime } from '@/modules/ai-runtime/providers/shared/mcp/base-provider-mcp.runtime.js';
|
||||
import {
|
||||
readJsonConfig,
|
||||
readObjectRecord,
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
readStringArray,
|
||||
readStringRecord,
|
||||
writeJsonConfig,
|
||||
} from '@/modules/llm/providers/runtimes/mcp-runtime.utils.js';
|
||||
} from '@/modules/ai-runtime/providers/shared/mcp/mcp-runtime.utils.js';
|
||||
|
||||
/**
|
||||
* Claude MCP runtime backed by `~/.claude.json` and project `.mcp.json`.
|
||||
@@ -2,8 +2,8 @@ import { readFile } from 'node:fs/promises';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
|
||||
import type { IProviderSkillsRuntime, ProviderSkill } from '@/modules/llm/providers/provider.interface.js';
|
||||
import { deduplicateSkills, listSkillsFromDirectory } from '@/modules/llm/providers/runtimes/skills-runtime.utils.js';
|
||||
import type { IProviderSkillsRuntime, ProviderSkill } from '@/modules/ai-runtime/types/index.js';
|
||||
import { deduplicateSkills, listSkillsFromDirectory } from '@/modules/ai-runtime/providers/shared/skills/skills-runtime.utils.js';
|
||||
|
||||
/**
|
||||
* Claude skills runtime backed by user/project/plugin skill directories.
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
import path from 'node:path';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
|
||||
import { BaseSdkProvider } from '@/modules/llm/providers/base-sdk.provider.js';
|
||||
import { BaseSdkProvider } from '@/modules/ai-runtime/providers/base/base-sdk.provider.js';
|
||||
import type {
|
||||
IProviderMcpRuntime,
|
||||
IProviderSkillsRuntime,
|
||||
@@ -15,9 +15,9 @@ import type {
|
||||
ProviderSessionEvent,
|
||||
RuntimePermissionMode,
|
||||
StartSessionInput,
|
||||
} from '@/modules/llm/providers/provider.interface.js';
|
||||
import { ClaudeMcpRuntime } from '@/modules/llm/providers/runtimes/claude-mcp.runtime.js';
|
||||
import { ClaudeSkillsRuntime } from '@/modules/llm/providers/runtimes/claude-skills.runtime.js';
|
||||
} from '@/modules/ai-runtime/types/index.js';
|
||||
import { ClaudeMcpRuntime } from '@/modules/ai-runtime/providers/claude/claude-mcp.runtime.js';
|
||||
import { ClaudeSkillsRuntime } from '@/modules/ai-runtime/providers/claude/claude-skills.runtime.js';
|
||||
|
||||
type ClaudeExecutionInput = StartSessionInput & {
|
||||
sessionId: string;
|
||||
@@ -6,8 +6,8 @@ import type {
|
||||
McpScope,
|
||||
ProviderMcpServer,
|
||||
UpsertProviderMcpServerInput,
|
||||
} from '@/modules/llm/providers/provider.interface.js';
|
||||
import { BaseProviderMcpRuntime } from '@/modules/llm/providers/runtimes/base-provider-mcp.runtime.js';
|
||||
} from '@/modules/ai-runtime/types/index.js';
|
||||
import { BaseProviderMcpRuntime } from '@/modules/ai-runtime/providers/shared/mcp/base-provider-mcp.runtime.js';
|
||||
import {
|
||||
readObjectRecord,
|
||||
readOptionalString,
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
readStringRecord,
|
||||
readTomlConfig,
|
||||
writeTomlConfig,
|
||||
} from '@/modules/llm/providers/runtimes/mcp-runtime.utils.js';
|
||||
} from '@/modules/ai-runtime/providers/shared/mcp/mcp-runtime.utils.js';
|
||||
|
||||
/**
|
||||
* Codex MCP runtime backed by user/project `.codex/config.toml`.
|
||||
@@ -1,13 +1,13 @@
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
|
||||
import type { IProviderSkillsRuntime, ProviderSkill, ProviderSkillScope } from '@/modules/llm/providers/provider.interface.js';
|
||||
import type { IProviderSkillsRuntime, ProviderSkill, ProviderSkillScope } from '@/modules/ai-runtime/types/index.js';
|
||||
import {
|
||||
deduplicateDirectories,
|
||||
deduplicateSkills,
|
||||
findGitRepoRoot,
|
||||
listSkillsFromDirectory,
|
||||
} from '@/modules/llm/providers/runtimes/skills-runtime.utils.js';
|
||||
} from '@/modules/ai-runtime/providers/shared/skills/skills-runtime.utils.js';
|
||||
|
||||
/**
|
||||
* Codex skills runtime backed by repo/user/admin/system skill directories.
|
||||
@@ -2,16 +2,16 @@ import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
|
||||
import { BaseSdkProvider } from '@/modules/llm/providers/base-sdk.provider.js';
|
||||
import { BaseSdkProvider } from '@/modules/ai-runtime/providers/base/base-sdk.provider.js';
|
||||
import type {
|
||||
IProviderMcpRuntime,
|
||||
IProviderSkillsRuntime,
|
||||
ProviderModel,
|
||||
ProviderSessionEvent,
|
||||
StartSessionInput,
|
||||
} from '@/modules/llm/providers/provider.interface.js';
|
||||
import { CodexMcpRuntime } from '@/modules/llm/providers/runtimes/codex-mcp.runtime.js';
|
||||
import { CodexSkillsRuntime } from '@/modules/llm/providers/runtimes/codex-skills.runtime.js';
|
||||
} from '@/modules/ai-runtime/types/index.js';
|
||||
import { CodexMcpRuntime } from '@/modules/ai-runtime/providers/codex/codex-mcp.runtime.js';
|
||||
import { CodexSkillsRuntime } from '@/modules/ai-runtime/providers/codex/codex-skills.runtime.js';
|
||||
import { AppError } from '@/shared/utils/app-error.js';
|
||||
|
||||
type CodexExecutionInput = StartSessionInput & {
|
||||
@@ -6,8 +6,8 @@ import type {
|
||||
McpScope,
|
||||
ProviderMcpServer,
|
||||
UpsertProviderMcpServerInput,
|
||||
} from '@/modules/llm/providers/provider.interface.js';
|
||||
import { BaseProviderMcpRuntime } from '@/modules/llm/providers/runtimes/base-provider-mcp.runtime.js';
|
||||
} from '@/modules/ai-runtime/types/index.js';
|
||||
import { BaseProviderMcpRuntime } from '@/modules/ai-runtime/providers/shared/mcp/base-provider-mcp.runtime.js';
|
||||
import {
|
||||
readJsonConfig,
|
||||
readObjectRecord,
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
readStringArray,
|
||||
readStringRecord,
|
||||
writeJsonConfig,
|
||||
} from '@/modules/llm/providers/runtimes/mcp-runtime.utils.js';
|
||||
} from '@/modules/ai-runtime/providers/shared/mcp/mcp-runtime.utils.js';
|
||||
|
||||
/**
|
||||
* Cursor MCP runtime backed by user/project `.cursor/mcp.json`.
|
||||
@@ -1,12 +1,12 @@
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
|
||||
import type { IProviderSkillsRuntime, ProviderSkill, ProviderSkillScope } from '@/modules/llm/providers/provider.interface.js';
|
||||
import type { IProviderSkillsRuntime, ProviderSkill, ProviderSkillScope } from '@/modules/ai-runtime/types/index.js';
|
||||
import {
|
||||
deduplicateDirectories,
|
||||
deduplicateSkills,
|
||||
listSkillsFromDirectory,
|
||||
} from '@/modules/llm/providers/runtimes/skills-runtime.utils.js';
|
||||
} from '@/modules/ai-runtime/providers/shared/skills/skills-runtime.utils.js';
|
||||
|
||||
/**
|
||||
* Cursor skills runtime backed by user/project skill directories.
|
||||
@@ -1,12 +1,12 @@
|
||||
import { BaseCliProvider } from '@/modules/llm/providers/base-cli.provider.js';
|
||||
import { BaseCliProvider } from '@/modules/ai-runtime/providers/base/base-cli.provider.js';
|
||||
import type {
|
||||
IProviderMcpRuntime,
|
||||
IProviderSkillsRuntime,
|
||||
ProviderModel,
|
||||
StartSessionInput,
|
||||
} from '@/modules/llm/providers/provider.interface.js';
|
||||
import { CursorMcpRuntime } from '@/modules/llm/providers/runtimes/cursor-mcp.runtime.js';
|
||||
import { CursorSkillsRuntime } from '@/modules/llm/providers/runtimes/cursor-skills.runtime.js';
|
||||
} from '@/modules/ai-runtime/types/index.js';
|
||||
import { CursorMcpRuntime } from '@/modules/ai-runtime/providers/cursor/cursor-mcp.runtime.js';
|
||||
import { CursorSkillsRuntime } from '@/modules/ai-runtime/providers/cursor/cursor-skills.runtime.js';
|
||||
|
||||
type CursorExecutionInput = StartSessionInput & {
|
||||
sessionId: string;
|
||||
@@ -6,8 +6,8 @@ import type {
|
||||
McpScope,
|
||||
ProviderMcpServer,
|
||||
UpsertProviderMcpServerInput,
|
||||
} from '@/modules/llm/providers/provider.interface.js';
|
||||
import { BaseProviderMcpRuntime } from '@/modules/llm/providers/runtimes/base-provider-mcp.runtime.js';
|
||||
} from '@/modules/ai-runtime/types/index.js';
|
||||
import { BaseProviderMcpRuntime } from '@/modules/ai-runtime/providers/shared/mcp/base-provider-mcp.runtime.js';
|
||||
import {
|
||||
readJsonConfig,
|
||||
readObjectRecord,
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
readStringArray,
|
||||
readStringRecord,
|
||||
writeJsonConfig,
|
||||
} from '@/modules/llm/providers/runtimes/mcp-runtime.utils.js';
|
||||
} from '@/modules/ai-runtime/providers/shared/mcp/mcp-runtime.utils.js';
|
||||
|
||||
/**
|
||||
* Gemini MCP runtime backed by user/project `.gemini/settings.json`.
|
||||
@@ -1,12 +1,12 @@
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
|
||||
import type { IProviderSkillsRuntime, ProviderSkill, ProviderSkillScope } from '@/modules/llm/providers/provider.interface.js';
|
||||
import type { IProviderSkillsRuntime, ProviderSkill, ProviderSkillScope } from '@/modules/ai-runtime/types/index.js';
|
||||
import {
|
||||
deduplicateDirectories,
|
||||
deduplicateSkills,
|
||||
listSkillsFromDirectory,
|
||||
} from '@/modules/llm/providers/runtimes/skills-runtime.utils.js';
|
||||
} from '@/modules/ai-runtime/providers/shared/skills/skills-runtime.utils.js';
|
||||
|
||||
/**
|
||||
* Gemini skills runtime backed by user/project skill directories.
|
||||
@@ -1,12 +1,12 @@
|
||||
import { BaseCliProvider } from '@/modules/llm/providers/base-cli.provider.js';
|
||||
import { BaseCliProvider } from '@/modules/ai-runtime/providers/base/base-cli.provider.js';
|
||||
import type {
|
||||
IProviderMcpRuntime,
|
||||
IProviderSkillsRuntime,
|
||||
ProviderModel,
|
||||
StartSessionInput,
|
||||
} from '@/modules/llm/providers/provider.interface.js';
|
||||
import { GeminiMcpRuntime } from '@/modules/llm/providers/runtimes/gemini-mcp.runtime.js';
|
||||
import { GeminiSkillsRuntime } from '@/modules/llm/providers/runtimes/gemini-skills.runtime.js';
|
||||
} from '@/modules/ai-runtime/types/index.js';
|
||||
import { GeminiMcpRuntime } from '@/modules/ai-runtime/providers/gemini/gemini-mcp.runtime.js';
|
||||
import { GeminiSkillsRuntime } from '@/modules/ai-runtime/providers/gemini/gemini-skills.runtime.js';
|
||||
|
||||
type GeminiExecutionInput = StartSessionInput & {
|
||||
sessionId: string;
|
||||
@@ -0,0 +1 @@
|
||||
export * from '@/modules/ai-runtime/types/index.js';
|
||||
@@ -6,13 +6,13 @@ import type {
|
||||
McpTransport,
|
||||
ProviderMcpServer,
|
||||
UpsertProviderMcpServerInput,
|
||||
} from '@/modules/llm/providers/provider.interface.js';
|
||||
} from '@/modules/ai-runtime/types/index.js';
|
||||
import {
|
||||
normalizeServerName,
|
||||
resolveWorkspacePath,
|
||||
runHttpServerProbe,
|
||||
runStdioServerProbe,
|
||||
} from '@/modules/llm/providers/runtimes/mcp-runtime.utils.js';
|
||||
} from '@/modules/ai-runtime/providers/shared/mcp/mcp-runtime.utils.js';
|
||||
|
||||
/**
|
||||
* Shared MCP runtime for provider-specific config readers/writers.
|
||||
@@ -5,7 +5,7 @@ import { once } from 'node:events';
|
||||
import spawn from 'cross-spawn';
|
||||
import TOML from '@iarna/toml';
|
||||
|
||||
import type { ProviderMcpServer } from '@/modules/llm/providers/provider.interface.js';
|
||||
import type { ProviderMcpServer } from '@/modules/ai-runtime/types/index.js';
|
||||
import { AppError } from '@/shared/utils/app-error.js';
|
||||
|
||||
/**
|
||||
@@ -2,7 +2,7 @@ import { access, readFile, readdir } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
|
||||
import type { LLMProvider } from '@/shared/types/app.js';
|
||||
import type { ProviderSkill, ProviderSkillScope } from '@/modules/llm/providers/provider.interface.js';
|
||||
import type { ProviderSkill, ProviderSkillScope } from '@/modules/ai-runtime/types/index.js';
|
||||
|
||||
/**
|
||||
* Tests whether a path exists.
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { LLMProvider } from '@/shared/types/app.js';
|
||||
import { AppError } from '@/shared/utils/app-error.js';
|
||||
import { llmProviderRegistry } from '@/modules/llm/llm.registry.js';
|
||||
import { llmProviderRegistry } from '@/modules/ai-runtime/ai-runtime.registry.js';
|
||||
import type {
|
||||
McpScope,
|
||||
ProviderMcpServer,
|
||||
@@ -10,7 +10,7 @@ import type {
|
||||
RuntimePermissionMode,
|
||||
StartSessionInput,
|
||||
UpsertProviderMcpServerInput,
|
||||
} from '@/modules/llm/providers/provider.interface.js';
|
||||
} from '@/modules/ai-runtime/types/index.js';
|
||||
|
||||
/**
|
||||
* Converts unknown request values into optional trimmed strings.
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ProviderSessionEvent } from '@/modules/llm/providers/provider.interface.js';
|
||||
import type { ProviderSessionEvent } from '@/modules/ai-runtime/types/index.js';
|
||||
import type { LLMProvider } from '@/shared/types/app.js';
|
||||
|
||||
export type UnifiedMessageType =
|
||||
@@ -3,7 +3,7 @@ import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { promises as fsPromises } from 'node:fs';
|
||||
|
||||
import { llmSessionsService } from '@/modules/llm/services/sessions.service.js';
|
||||
import { llmSessionsService } from '@/modules/ai-runtime/services/sessions.service.js';
|
||||
import type { LLMProvider } from '@/shared/types/app.js';
|
||||
import { logger } from '@/shared/utils/logger.js';
|
||||
|
||||
@@ -5,8 +5,8 @@ import { scanStateDb } from '@/shared/database/repositories/scan-state.db.js';
|
||||
import { sessionsDb } from '@/shared/database/repositories/sessions.db.js';
|
||||
import type { LLMProvider } from '@/shared/types/app.js';
|
||||
import { AppError } from '@/shared/utils/app-error.js';
|
||||
import { sessionIndexers } from '@/modules/llm/session-indexers/index.js';
|
||||
import { llmMessagesUnifier, type UnifiedChatMessage } from '@/modules/llm/services/messages-unifier.service.js';
|
||||
import { sessionIndexers } from '@/modules/ai-runtime/session-indexers/index.js';
|
||||
import { llmMessagesUnifier, type UnifiedChatMessage } from '@/modules/ai-runtime/services/messages-unifier.service.js';
|
||||
|
||||
type SyncResult = {
|
||||
processedByProvider: Record<LLMProvider, number>;
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
findFilesRecursivelyCreatedAfter,
|
||||
normalizeSessionName,
|
||||
readFileTimestamps,
|
||||
} from '@/modules/llm/session-indexers/session-indexer.utils.js';
|
||||
import type { ISessionIndexer } from '@/modules/llm/session-indexers/session-indexer.interface.js';
|
||||
} from '@/modules/ai-runtime/session-indexers/session-indexer.utils.js';
|
||||
import type { ISessionIndexer } from '@/modules/ai-runtime/session-indexers/session-indexer.interface.js';
|
||||
|
||||
type ParsedSession = {
|
||||
sessionId: string;
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
findFilesRecursivelyCreatedAfter,
|
||||
normalizeSessionName,
|
||||
readFileTimestamps,
|
||||
} from '@/modules/llm/session-indexers/session-indexer.utils.js';
|
||||
import type { ISessionIndexer } from '@/modules/llm/session-indexers/session-indexer.interface.js';
|
||||
} from '@/modules/ai-runtime/session-indexers/session-indexer.utils.js';
|
||||
import type { ISessionIndexer } from '@/modules/ai-runtime/session-indexers/session-indexer.interface.js';
|
||||
|
||||
type ParsedSession = {
|
||||
sessionId: string;
|
||||
@@ -11,8 +11,8 @@ import {
|
||||
listDirectoryEntriesSafe,
|
||||
normalizeSessionName,
|
||||
readFileTimestamps,
|
||||
} from '@/modules/llm/session-indexers/session-indexer.utils.js';
|
||||
import type { ISessionIndexer } from '@/modules/llm/session-indexers/session-indexer.interface.js';
|
||||
} from '@/modules/ai-runtime/session-indexers/session-indexer.utils.js';
|
||||
import type { ISessionIndexer } from '@/modules/ai-runtime/session-indexers/session-indexer.interface.js';
|
||||
|
||||
type ParsedSession = {
|
||||
sessionId: string;
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
findFilesRecursivelyCreatedAfter,
|
||||
normalizeSessionName,
|
||||
readFileTimestamps,
|
||||
} from '@/modules/llm/session-indexers/session-indexer.utils.js';
|
||||
import type { ISessionIndexer } from '@/modules/llm/session-indexers/session-indexer.interface.js';
|
||||
} from '@/modules/ai-runtime/session-indexers/session-indexer.utils.js';
|
||||
import type { ISessionIndexer } from '@/modules/ai-runtime/session-indexers/session-indexer.interface.js';
|
||||
|
||||
type ParsedSession = {
|
||||
sessionId: string;
|
||||
15
server/src/modules/ai-runtime/session-indexers/index.ts
Normal file
15
server/src/modules/ai-runtime/session-indexers/index.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { ISessionIndexer } from '@/modules/ai-runtime/session-indexers/session-indexer.interface.js';
|
||||
import { ClaudeSessionIndexer } from '@/modules/ai-runtime/session-indexers/claude.session-indexer.js';
|
||||
import { CodexSessionIndexer } from '@/modules/ai-runtime/session-indexers/codex.session-indexer.js';
|
||||
import { CursorSessionIndexer } from '@/modules/ai-runtime/session-indexers/cursor.session-indexer.js';
|
||||
import { GeminiSessionIndexer } from '@/modules/ai-runtime/session-indexers/gemini.session-indexer.js';
|
||||
|
||||
/**
|
||||
* Provider-specific session indexers used by the sync orchestrator.
|
||||
*/
|
||||
export const sessionIndexers: ISessionIndexer[] = [
|
||||
new ClaudeSessionIndexer(),
|
||||
new CodexSessionIndexer(),
|
||||
new CursorSessionIndexer(),
|
||||
new GeminiSessionIndexer(),
|
||||
];
|
||||
@@ -6,11 +6,11 @@ import test from 'node:test';
|
||||
|
||||
import { AppError } from '@/shared/utils/app-error.js';
|
||||
import { llmAssetsService } from '@/modules/assets/assets.service.js';
|
||||
import { ClaudeProvider } from '@/modules/llm/providers/claude.provider.js';
|
||||
import { CodexProvider } from '@/modules/llm/providers/codex.provider.js';
|
||||
import { CursorProvider } from '@/modules/llm/providers/cursor.provider.js';
|
||||
import { GeminiProvider } from '@/modules/llm/providers/gemini.provider.js';
|
||||
import { llmService } from '@/modules/llm/services/llm.service.js';
|
||||
import { ClaudeProvider } from '@/modules/ai-runtime/providers/claude/claude.provider.js';
|
||||
import { CodexProvider } from '@/modules/ai-runtime/providers/codex/codex.provider.js';
|
||||
import { CursorProvider } from '@/modules/ai-runtime/providers/cursor/cursor.provider.js';
|
||||
import { GeminiProvider } from '@/modules/ai-runtime/providers/gemini/gemini.provider.js';
|
||||
import { llmService } from '@/modules/ai-runtime/services/ai-runtime.service.js';
|
||||
|
||||
const asyncEvents = async function* (events: unknown[]) {
|
||||
for (const event of events) {
|
||||
@@ -8,7 +8,7 @@ import test from 'node:test';
|
||||
import TOML from '@iarna/toml';
|
||||
|
||||
import { AppError } from '@/shared/utils/app-error.js';
|
||||
import { llmService } from '@/modules/llm/services/llm.service.js';
|
||||
import { llmService } from '@/modules/ai-runtime/services/ai-runtime.service.js';
|
||||
|
||||
const patchHomeDir = (nextHomeDir: string) => {
|
||||
const original = os.homedir;
|
||||
@@ -1,7 +1,7 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import { llmMessagesUnifier } from '@/modules/llm/services/messages-unifier.service.js';
|
||||
import { llmMessagesUnifier } from '@/modules/ai-runtime/services/messages-unifier.service.js';
|
||||
|
||||
/**
|
||||
* This test covers helper-3 Claude normalization: user/assistant/thinking/tool-use/tool-result/error.
|
||||
@@ -5,11 +5,11 @@ import path from 'node:path';
|
||||
import test from 'node:test';
|
||||
|
||||
import { AppError } from '@/shared/utils/app-error.js';
|
||||
import { llmService } from '@/modules/llm/services/llm.service.js';
|
||||
import { CursorProvider } from '@/modules/llm/providers/cursor.provider.js';
|
||||
import { GeminiProvider } from '@/modules/llm/providers/gemini.provider.js';
|
||||
import { CodexProvider } from '@/modules/llm/providers/codex.provider.js';
|
||||
import { ClaudeProvider } from '@/modules/llm/providers/claude.provider.js';
|
||||
import { llmService } from '@/modules/ai-runtime/services/ai-runtime.service.js';
|
||||
import { CursorProvider } from '@/modules/ai-runtime/providers/cursor/cursor.provider.js';
|
||||
import { GeminiProvider } from '@/modules/ai-runtime/providers/gemini/gemini.provider.js';
|
||||
import { CodexProvider } from '@/modules/ai-runtime/providers/codex/codex.provider.js';
|
||||
import { ClaudeProvider } from '@/modules/ai-runtime/providers/claude/claude.provider.js';
|
||||
|
||||
const asyncEvents = async function* (events: unknown[]) {
|
||||
for (const event of events) {
|
||||
@@ -7,10 +7,10 @@ import test from 'node:test';
|
||||
import { AppError } from '@/shared/utils/app-error.js';
|
||||
import { scanStateDb } from '@/shared/database/repositories/scan-state.db.js';
|
||||
import { sessionsDb } from '@/shared/database/repositories/sessions.db.js';
|
||||
import { llmSessionsService } from '@/modules/llm/services/sessions.service.js';
|
||||
import { sessionIndexers } from '@/modules/llm/session-indexers/index.js';
|
||||
import { llmSessionsService } from '@/modules/ai-runtime/services/sessions.service.js';
|
||||
import { sessionIndexers } from '@/modules/ai-runtime/session-indexers/index.js';
|
||||
import { conversationSearchService } from '@/modules/conversations/conversation-search.service.js';
|
||||
import type { ISessionIndexer } from '@/modules/llm/session-indexers/session-indexer.interface.js';
|
||||
import type { ISessionIndexer } from '@/modules/ai-runtime/session-indexers/session-indexer.interface.js';
|
||||
|
||||
const patchMethod = <T extends object, K extends keyof T>(target: T, key: K, replacement: T[K]) => {
|
||||
const original = target[key];
|
||||
@@ -4,7 +4,7 @@ import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import test from 'node:test';
|
||||
|
||||
import { llmService } from '@/modules/llm/services/llm.service.js';
|
||||
import { llmService } from '@/modules/ai-runtime/services/ai-runtime.service.js';
|
||||
|
||||
const patchHomeDir = (nextHomeDir: string) => {
|
||||
const original = os.homedir;
|
||||
3
server/src/modules/ai-runtime/types/index.ts
Normal file
3
server/src/modules/ai-runtime/types/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from '@/modules/ai-runtime/types/provider.types.js';
|
||||
export * from '@/modules/ai-runtime/types/mcp.types.js';
|
||||
export * from '@/modules/ai-runtime/types/skills.types.js';
|
||||
66
server/src/modules/ai-runtime/types/mcp.types.ts
Normal file
66
server/src/modules/ai-runtime/types/mcp.types.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import type { LLMProvider } from '@/shared/types/app.js';
|
||||
|
||||
export type McpScope = 'user' | 'local' | 'project';
|
||||
|
||||
export type McpTransport = 'stdio' | 'http' | 'sse';
|
||||
|
||||
/**
|
||||
* Provider MCP server descriptor normalized for frontend consumption.
|
||||
*/
|
||||
export type ProviderMcpServer = {
|
||||
provider: LLMProvider;
|
||||
name: string;
|
||||
scope: McpScope;
|
||||
transport: McpTransport;
|
||||
command?: string;
|
||||
args?: string[];
|
||||
env?: Record<string, string>;
|
||||
cwd?: string;
|
||||
url?: string;
|
||||
headers?: Record<string, string>;
|
||||
envVars?: string[];
|
||||
bearerTokenEnvVar?: string;
|
||||
envHttpHeaders?: Record<string, string>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Shared payload shape for MCP server create/update operations.
|
||||
*/
|
||||
export type UpsertProviderMcpServerInput = {
|
||||
name: string;
|
||||
scope?: McpScope;
|
||||
transport: McpTransport;
|
||||
workspacePath?: string;
|
||||
command?: string;
|
||||
args?: string[];
|
||||
env?: Record<string, string>;
|
||||
cwd?: string;
|
||||
url?: string;
|
||||
headers?: Record<string, string>;
|
||||
envVars?: string[];
|
||||
bearerTokenEnvVar?: string;
|
||||
envHttpHeaders?: Record<string, string>;
|
||||
};
|
||||
|
||||
/**
|
||||
* MCP runtime contract for one provider.
|
||||
*/
|
||||
export interface IProviderMcpRuntime {
|
||||
listServers(options?: { workspacePath?: string }): Promise<Record<McpScope, ProviderMcpServer[]>>;
|
||||
listServersForScope(scope: McpScope, options?: { workspacePath?: string }): Promise<ProviderMcpServer[]>;
|
||||
upsertServer(input: UpsertProviderMcpServerInput): Promise<ProviderMcpServer>;
|
||||
removeServer(
|
||||
input: { name: string; scope?: McpScope; workspacePath?: string },
|
||||
): Promise<{ removed: boolean; provider: LLMProvider; name: string; scope: McpScope }>;
|
||||
runServer(
|
||||
input: { name: string; scope?: McpScope; workspacePath?: string },
|
||||
): Promise<{
|
||||
provider: LLMProvider;
|
||||
name: string;
|
||||
scope: McpScope;
|
||||
transport: McpTransport;
|
||||
reachable: boolean;
|
||||
statusCode?: number;
|
||||
error?: string;
|
||||
}>;
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
import type { LLMProvider } from '@/shared/types/app.js';
|
||||
import type { IProviderMcpRuntime } from '@/modules/ai-runtime/types/mcp.types.js';
|
||||
import type { IProviderSkillsRuntime } from '@/modules/ai-runtime/types/skills.types.js';
|
||||
|
||||
export type ProviderExecutionFamily = 'sdk' | 'cli';
|
||||
|
||||
@@ -6,12 +8,6 @@ export type ProviderSessionStatus = 'running' | 'completed' | 'failed' | 'stoppe
|
||||
|
||||
export type RuntimePermissionMode = 'ask' | 'allow' | 'deny';
|
||||
|
||||
export type McpScope = 'user' | 'local' | 'project';
|
||||
|
||||
export type McpTransport = 'stdio' | 'http' | 'sse';
|
||||
|
||||
export type ProviderSkillScope = 'user' | 'project' | 'plugin' | 'repo' | 'admin' | 'system';
|
||||
|
||||
/**
|
||||
* Advertises optional provider behaviors so route/service code can gate features.
|
||||
*/
|
||||
@@ -20,57 +16,6 @@ export type ProviderCapabilities = {
|
||||
supportsThinkingModeControl: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Provider MCP server descriptor normalized for frontend consumption.
|
||||
*/
|
||||
export type ProviderMcpServer = {
|
||||
provider: LLMProvider;
|
||||
name: string;
|
||||
scope: McpScope;
|
||||
transport: McpTransport;
|
||||
command?: string;
|
||||
args?: string[];
|
||||
env?: Record<string, string>;
|
||||
cwd?: string;
|
||||
url?: string;
|
||||
headers?: Record<string, string>;
|
||||
envVars?: string[];
|
||||
bearerTokenEnvVar?: string;
|
||||
envHttpHeaders?: Record<string, string>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Shared payload shape for MCP server create/update operations.
|
||||
*/
|
||||
export type UpsertProviderMcpServerInput = {
|
||||
name: string;
|
||||
scope?: McpScope;
|
||||
transport: McpTransport;
|
||||
workspacePath?: string;
|
||||
command?: string;
|
||||
args?: string[];
|
||||
env?: Record<string, string>;
|
||||
cwd?: string;
|
||||
url?: string;
|
||||
headers?: Record<string, string>;
|
||||
envVars?: string[];
|
||||
bearerTokenEnvVar?: string;
|
||||
envHttpHeaders?: Record<string, string>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Unified skill descriptor returned by provider skill runtimes.
|
||||
*/
|
||||
export type ProviderSkill = {
|
||||
provider: LLMProvider;
|
||||
scope: ProviderSkillScope;
|
||||
name: string;
|
||||
description?: string;
|
||||
invocation: string;
|
||||
filePath: string;
|
||||
pluginName?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Provider model descriptor normalized for frontend consumption.
|
||||
*/
|
||||
@@ -145,36 +90,6 @@ export interface IProvider {
|
||||
listSessions(): ProviderSessionSnapshot[];
|
||||
}
|
||||
|
||||
/**
|
||||
* MCP runtime contract for one provider.
|
||||
*/
|
||||
export interface IProviderMcpRuntime {
|
||||
listServers(options?: { workspacePath?: string }): Promise<Record<McpScope, ProviderMcpServer[]>>;
|
||||
listServersForScope(scope: McpScope, options?: { workspacePath?: string }): Promise<ProviderMcpServer[]>;
|
||||
upsertServer(input: UpsertProviderMcpServerInput): Promise<ProviderMcpServer>;
|
||||
removeServer(
|
||||
input: { name: string; scope?: McpScope; workspacePath?: string },
|
||||
): Promise<{ removed: boolean; provider: LLMProvider; name: string; scope: McpScope }>;
|
||||
runServer(
|
||||
input: { name: string; scope?: McpScope; workspacePath?: string },
|
||||
): Promise<{
|
||||
provider: LLMProvider;
|
||||
name: string;
|
||||
scope: McpScope;
|
||||
transport: McpTransport;
|
||||
reachable: boolean;
|
||||
statusCode?: number;
|
||||
error?: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skills runtime contract for one provider.
|
||||
*/
|
||||
export interface IProviderSkillsRuntime {
|
||||
listSkills(options?: { workspacePath?: string }): Promise<ProviderSkill[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal mutable session state used by provider base classes.
|
||||
*/
|
||||
23
server/src/modules/ai-runtime/types/skills.types.ts
Normal file
23
server/src/modules/ai-runtime/types/skills.types.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import type { LLMProvider } from '@/shared/types/app.js';
|
||||
|
||||
export type ProviderSkillScope = 'user' | 'project' | 'plugin' | 'repo' | 'admin' | 'system';
|
||||
|
||||
/**
|
||||
* Unified skill descriptor returned by provider skill runtimes.
|
||||
*/
|
||||
export type ProviderSkill = {
|
||||
provider: LLMProvider;
|
||||
scope: ProviderSkillScope;
|
||||
name: string;
|
||||
description?: string;
|
||||
invocation: string;
|
||||
filePath: string;
|
||||
pluginName?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Skills runtime contract for one provider.
|
||||
*/
|
||||
export interface IProviderSkillsRuntime {
|
||||
listSkills(options?: { workspacePath?: string }): Promise<ProviderSkill[]>;
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import os from 'os';
|
||||
import TOML from '@iarna/toml';
|
||||
import { getCodexSessions } from '../../../projects.js';
|
||||
import { sessionsDb } from '@/shared/database/repositories/sessions.db.js';
|
||||
import { llmSessionsService } from '@/modules/llm/services/sessions.service.js';
|
||||
import { llmSessionsService } from '@/modules/ai-runtime/services/sessions.service.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import express from 'express';
|
||||
import sessionManager from '../../../sessionManager.js';
|
||||
import { llmSessionsService } from '@/modules/llm/services/sessions.service.js';
|
||||
import { llmSessionsService } from '@/modules/ai-runtime/services/sessions.service.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import type { ISessionIndexer } from '@/modules/llm/session-indexers/session-indexer.interface.js';
|
||||
import { ClaudeSessionIndexer } from '@/modules/llm/session-indexers/claude.session-indexer.js';
|
||||
import { CodexSessionIndexer } from '@/modules/llm/session-indexers/codex.session-indexer.js';
|
||||
import { CursorSessionIndexer } from '@/modules/llm/session-indexers/cursor.session-indexer.js';
|
||||
import { GeminiSessionIndexer } from '@/modules/llm/session-indexers/gemini.session-indexer.js';
|
||||
|
||||
/**
|
||||
* Provider-specific session indexers used by the sync orchestrator.
|
||||
*/
|
||||
export const sessionIndexers: ISessionIndexer[] = [
|
||||
new ClaudeSessionIndexer(),
|
||||
new CodexSessionIndexer(),
|
||||
new CursorSessionIndexer(),
|
||||
new GeminiSessionIndexer(),
|
||||
];
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
} from '../../../projects.js';
|
||||
import { sessionsDb } from '@/shared/database/repositories/sessions.db.js';
|
||||
import { workspaceOriginalPathsDb } from '@/shared/database/repositories/workspace-original-paths.db.js';
|
||||
import { llmSessionsService } from '@/modules/llm/services/sessions.service.js';
|
||||
import { llmSessionsService } from '@/modules/ai-runtime/services/sessions.service.js';
|
||||
import { authenticateToken } from '../auth/auth.middleware.js';
|
||||
import { getWorkspaceNameFromPath, WORKSPACES_ROOT, validateWorkspacePath } from './projects.utils.js';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import path from 'node:path';
|
||||
|
||||
import { llmSessionsService } from '@/modules/llm/services/sessions.service.js';
|
||||
import { llmSessionsService } from '@/modules/ai-runtime/services/sessions.service.js';
|
||||
import { sessionsDb } from '@/shared/database/repositories/sessions.db.js';
|
||||
import { workspaceOriginalPathsDb } from '@/shared/database/repositories/workspace-original-paths.db.js';
|
||||
import type { SessionsRow } from '@/shared/database/types.js';
|
||||
|
||||
@@ -8,7 +8,7 @@ import { dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
import { initializeDatabase } from '@/shared/database/init-db.js';
|
||||
import { initializeWatcher } from '@/modules/llm/services/sessions-watcher.service.js';
|
||||
import { initializeWatcher } from '@/modules/ai-runtime/services/sessions-watcher.service.js';
|
||||
import { configureWebPush } from '@/modules/push-sub/push-sub.services.js';
|
||||
import { getConnectableHost } from '@/shared/utils/networkHosts.js';
|
||||
import { logger } from '@/shared/utils/logger.js';
|
||||
@@ -92,7 +92,7 @@ const [
|
||||
importRoute('./modules/workspaces/workspaces.routes.js'),
|
||||
importRoute('./modules/projects/projects.inline.routes.js'),
|
||||
importRoute('./modules/files/files.routes.js'),
|
||||
importRoute('./modules/llm/llm.routes.js'),
|
||||
importRoute('./modules/ai-runtime/ai-runtime.routes.js'),
|
||||
importRoute('./modules/assets/assets.routes.js'),
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user