feat(coding): add core host api composition

This commit is contained in:
2026-08-23 20:00:35 +08:00
parent 98bac20639
commit 22b4a9f9c4
23 changed files with 2258 additions and 59 deletions

View File

@@ -7,10 +7,15 @@ import type {
ProductCodingSkill,
ProductPiCommandInput,
} from '../../shared/coding-product-tools';
import { createCodingConversationStore } from '../coding-projects/conversation-store';
import type { CodingAttachmentStore } from '../coding-projects/attachment-store';
import { readCodingProjectConfigV2 } from '../coding-projects/project-config';
import { CodingProjectFileService } from '../coding-projects/project-files';
import {
CodingProjectServiceError,
type CodingProjectService,
} from '../coding-projects/project-service';
import type { CodingConversationService } from '../coding-runtime/conversation-service';
import type { CodingConversationRuntime } from '../coding-runtime/contracts';
import type { PiProductTools } from '../coding-runtime/pi/product-tools';
export interface ActiveCodingProject {
@@ -31,7 +36,11 @@ export interface CodingProductHost {
export interface CodingProductComposition {
attachments: CodingAttachmentStore;
productTools: PiProductTools;
projects: CodingProjectService;
conversations: CodingConversationService;
runtime: CodingConversationRuntime;
host: CodingProductHost;
shutdown(): Promise<void>;
}
export class CodingProductHostError extends Error {
@@ -45,7 +54,7 @@ export class CodingProductHostError extends Error {
}
export interface CodingProductHostOptions {
getActiveProject(): Promise<ActiveCodingProject | null>;
projects: Pick<CodingProjectService, 'getActiveProject' | 'findActiveConversation'>;
productTools: PiProductTools;
files?: CodingProjectFileService;
listPiCommands?(conversationId: string): Promise<unknown>;
@@ -77,7 +86,7 @@ export function createCodingProductHost(options: CodingProductHostOptions): Codi
const files = options.files ?? new CodingProjectFileService();
async function activeProject(): Promise<ActiveCodingProject> {
const project = await options.getActiveProject();
const project = await options.projects.getActiveProject();
if (!project) {
throw new CodingProductHostError(
409,
@@ -118,15 +127,17 @@ export function createCodingProductHost(options: CodingProductHostOptions): Codi
project: ActiveCodingProject;
skillIds: readonly string[];
}> {
const project = await activeProject();
const conversation = await createCodingConversationStore(project.path).get(conversationId);
if (!conversation) {
throw new CodingProductHostError(
404,
'CODING_CONVERSATION_NOT_FOUND',
'Coding Conversation does not exist',
);
let context;
try {
context = await options.projects.findActiveConversation(conversationId);
} catch (error) {
if (error instanceof CodingProjectServiceError
&& (error.status === 404 || error.status === 409)) {
throw new CodingProductHostError(error.status, error.code, error.message);
}
throw error;
}
const { project, conversation } = context;
return {
project,
skillIds: await selectedSkillIds(project.path, conversation.agentId),