Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 61 additions & 9 deletions packages/ai/src/apply/client.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
import OpenAI from 'openai';

import type { ApplyCodeChangeAssessment, ApplyCodeChangeGateOptions } from './quality';
import { assessCodeChange, shouldBlockApply } from './quality';

export interface ApplyCodeChangeMetadata {
userId?: string;
projectId?: string;
conversationId?: string;
}

export interface ApplyCodeChangeQualityOptions {
gate?: ApplyCodeChangeGateOptions;
blockBeforeProvider?: boolean;
}

export interface ApplyCodeChangeWithQualityResult {
code: string | null;
preflightAssessment: ApplyCodeChangeAssessment;
resultAssessment?: ApplyCodeChangeAssessment;
blocked: boolean;
blockReason?: string;
}

interface RelaceApplyResponse {
mergedCode?: string | null;
}

const createPrompt = (originalCode: string, updateSnippet: string, instruction: string) =>
`<instruction>${instruction}</instruction>\n<code>${originalCode}</code>\n<update>${updateSnippet}</update>`;

Expand Down Expand Up @@ -37,7 +57,7 @@ export async function applyCodeChangeWithMorph(
},
],
});
return response.choices[0]?.message.content || null;
return response.choices[0]?.message.content ?? null;
}

export async function applyCodeChangeWithRelace(
Expand Down Expand Up @@ -77,8 +97,8 @@ export async function applyCodeChangeWithRelace(
if (!response.ok) {
throw new Error(`Failed to apply code change: ${response.status}`);
}
const result = await response.json();
return result.mergedCode;
const result = (await response.json()) as RelaceApplyResponse;
return result.mergedCode ?? null;
}

export async function applyCodeChange(
Expand Down Expand Up @@ -118,12 +138,7 @@ export async function applyCodeChange(
updateSnippet,
instruction,
)
: await (applyFn as typeof applyCodeChangeWithRelace)(
originalCode,
updateSnippet,
instruction,
metadata,
);
: await applyFn(originalCode, updateSnippet, instruction, metadata);
if (result) return result;
} catch (error) {
console.warn(`Code application failed with provider ${provider}:`, error);
Expand All @@ -133,3 +148,40 @@ export async function applyCodeChange(

return null;
}

export async function applyCodeChangeWithQuality(
originalCode: string,
updateSnippet: string,
instruction: string,
metadata?: ApplyCodeChangeMetadata,
preferredProvider: FastApplyProvider = FastApplyProvider.MORPH,
options: ApplyCodeChangeQualityOptions = {},
): Promise<ApplyCodeChangeWithQualityResult> {
const preflightAssessment = assessCodeChange(originalCode, updateSnippet, instruction);
if (options.blockBeforeProvider && shouldBlockApply(preflightAssessment, options.gate)) {
return {
code: null,
preflightAssessment,
blocked: true,
blockReason:
preflightAssessment.blockingConcerns[0] ??
`Preflight score ${preflightAssessment.score} is below the configured gate.`,
};
}

const code = await applyCodeChange(
originalCode,
updateSnippet,
instruction,
metadata,
preferredProvider,
);
return {
code,
preflightAssessment,
resultAssessment: code
? assessCodeChange(originalCode, updateSnippet, instruction, code)
: undefined,
blocked: false,
};
}
1 change: 1 addition & 0 deletions packages/ai/src/apply/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './client';
export * from './quality';
Loading