feat(coding): add core host api composition
This commit is contained in:
@@ -10,6 +10,7 @@ import type { AgentBrowserModule } from '../../electron/agent-browser';
|
||||
import {
|
||||
CodingProductHostError,
|
||||
createCodingProductHost,
|
||||
type CodingProductHostOptions,
|
||||
} from '../../electron/api/coding-product-services';
|
||||
import { CodingAttachmentStore } from '../../electron/coding-projects/attachment-store';
|
||||
import { createCodingConversationStore } from '../../electron/coding-projects/conversation-store';
|
||||
@@ -65,6 +66,35 @@ function productTools(root: string): PiProductTools {
|
||||
});
|
||||
}
|
||||
|
||||
function projectService(
|
||||
root: string,
|
||||
active = true,
|
||||
): CodingProductHostOptions['projects'] {
|
||||
const project = {
|
||||
id: 'project-a',
|
||||
path: root,
|
||||
name: 'project-a',
|
||||
createdAt: '2026-08-23T00:00:00.000Z',
|
||||
updatedAt: '2026-08-23T00:00:00.000Z',
|
||||
lastOpenedAt: '2026-08-23T00:00:00.000Z',
|
||||
};
|
||||
return {
|
||||
getActiveProject: async () => active ? project : null,
|
||||
findActiveConversation: async (id) => {
|
||||
if (!active) throw new Error('No active project');
|
||||
const conversation = await createCodingConversationStore(root).get(id);
|
||||
if (!conversation) {
|
||||
throw new CodingProductHostError(
|
||||
404,
|
||||
'CODING_CONVERSATION_NOT_FOUND',
|
||||
'Coding Conversation does not exist',
|
||||
);
|
||||
}
|
||||
return { project, conversation };
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function git(root: string, ...args: string[]): Promise<void> {
|
||||
await exec('git', ['-C', root, ...args], { windowsHide: true });
|
||||
}
|
||||
@@ -78,7 +108,7 @@ describe('PI-105 product Host composition', () => {
|
||||
const root = await configuredProject();
|
||||
const tools = productTools(root);
|
||||
const host = createCodingProductHost({
|
||||
getActiveProject: async () => ({ id: 'project-a', path: root }),
|
||||
projects: projectService(root),
|
||||
productTools: tools,
|
||||
listPiCommands: async () => ({
|
||||
commands: [
|
||||
@@ -113,7 +143,7 @@ describe('PI-105 product Host composition', () => {
|
||||
await writeFile(path.join(root, 'notes.txt'), 'baseline\n', 'utf8');
|
||||
const tools = productTools(root);
|
||||
const host = createCodingProductHost({
|
||||
getActiveProject: async () => ({ id: 'project-a', path: root }),
|
||||
projects: projectService(root),
|
||||
productTools: tools,
|
||||
});
|
||||
await tools.beginRun({ conversationId, runId: 'run-a', projectPath: root });
|
||||
@@ -145,7 +175,7 @@ describe('PI-105 product Host composition', () => {
|
||||
|
||||
const tools = productTools(root);
|
||||
const host = createCodingProductHost({
|
||||
getActiveProject: async () => ({ id: 'project-a', path: root }),
|
||||
projects: projectService(root),
|
||||
productTools: tools,
|
||||
});
|
||||
await tools.beginRun({ conversationId, runId: 'run-conflict', projectPath: root });
|
||||
@@ -165,7 +195,7 @@ describe('PI-105 product Host composition', () => {
|
||||
const root = await configuredProject();
|
||||
const tools = productTools(root);
|
||||
const unavailable = createCodingProductHost({
|
||||
getActiveProject: async () => null,
|
||||
projects: projectService(root, false),
|
||||
productTools: tools,
|
||||
});
|
||||
await expect(unavailable.fileStatus()).rejects.toMatchObject<CodingProductHostError>({
|
||||
@@ -173,7 +203,7 @@ describe('PI-105 product Host composition', () => {
|
||||
});
|
||||
|
||||
const host = createCodingProductHost({
|
||||
getActiveProject: async () => ({ id: 'project-a', path: root }),
|
||||
projects: projectService(root),
|
||||
productTools: tools,
|
||||
});
|
||||
await expect(host.listSkills('missing')).rejects.toMatchObject<CodingProductHostError>({
|
||||
|
||||
Reference in New Issue
Block a user